This is an automated email from the ASF dual-hosted git repository.

dataroaring pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new ac7984ef3fc [improvement](meta) Serialize meta via gson part2 (#36480)
ac7984ef3fc is described below

commit ac7984ef3fcf61025919498df6eb33ae0b282201
Author: Yongqiang YANG <[email protected]>
AuthorDate: Fri Jun 21 17:32:21 2024 +0800

    [improvement](meta) Serialize meta via gson part2 (#36480)
    
    iszhangpch handles most of work.
    dataroaring handles upgrading mtmv by introducing GsonUtils134.
    
    Co-authored-by: iszhangpch
---
 .../org/apache/doris/common/FeMetaVersion.java     |  4 +-
 .../doris/alter/BatchAlterJobPersistInfo.java      | 26 +++++---
 .../java/org/apache/doris/analysis/TableRef.java   | 27 ++++----
 .../java/org/apache/doris/backup/AbstractJob.java  | 12 ++++
 .../java/org/apache/doris/backup/BackupJob.java    | 23 +++++--
 .../org/apache/doris/backup/BackupJobInfo.java     | 24 ++++---
 .../java/org/apache/doris/backup/BackupMeta.java   | 11 +++-
 .../apache/doris/backup/RestoreFileMapping.java    | 40 +++++------
 .../java/org/apache/doris/backup/RestoreJob.java   | 41 ++++++++++--
 .../java/org/apache/doris/backup/SnapshotInfo.java | 38 ++++++-----
 .../apache/doris/catalog/FunctionSearchDesc.java   | 27 +++++---
 .../main/java/org/apache/doris/catalog/MTMV.java   | 13 +++-
 .../org/apache/doris/persist/gson/GsonUtils.java   | 77 +++++++++++++++++++---
 .../gson/{GsonUtils.java => GsonUtils134.java}     |  2 +-
 .../persist/gson/RuntimeTypeAdapterFactory.java    |  5 +-
 .../org/apache/doris/backup/BackupJobTest.java     | 35 ++++++++++
 .../org/apache/doris/backup/RestoreJobTest.java    | 30 +++++++++
 17 files changed, 331 insertions(+), 104 deletions(-)

diff --git 
a/fe/fe-common/src/main/java/org/apache/doris/common/FeMetaVersion.java 
b/fe/fe-common/src/main/java/org/apache/doris/common/FeMetaVersion.java
index 5f7b7991e00..a54d30d294e 100644
--- a/fe/fe-common/src/main/java/org/apache/doris/common/FeMetaVersion.java
+++ b/fe/fe-common/src/main/java/org/apache/doris/common/FeMetaVersion.java
@@ -90,8 +90,10 @@ public final class FeMetaVersion {
     public static final int VERSION_133 = 133;
     // For mate gson
     public static final int VERSION_134 = 134;
+    // For mate gson
+    public static final int VERSION_135 = 135;
     // note: when increment meta version, should assign the latest version to 
VERSION_CURRENT
-    public static final int VERSION_CURRENT = VERSION_134;
+    public static final int VERSION_CURRENT = VERSION_135;
 
     // all logs meta version should >= the minimum version, so that we could 
remove many if clause, for example
     // if (FE_METAVERSION < VERSION_94) ...
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/alter/BatchAlterJobPersistInfo.java 
b/fe/fe-core/src/main/java/org/apache/doris/alter/BatchAlterJobPersistInfo.java
index 3d6caefee50..b9313302c3c 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/alter/BatchAlterJobPersistInfo.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/alter/BatchAlterJobPersistInfo.java
@@ -17,7 +17,13 @@
 
 package org.apache.doris.alter;
 
+import org.apache.doris.catalog.Env;
+import org.apache.doris.common.FeMetaVersion;
+import org.apache.doris.common.io.Text;
 import org.apache.doris.common.io.Writable;
+import org.apache.doris.persist.gson.GsonUtils;
+
+import com.google.gson.annotations.SerializedName;
 
 import java.io.DataInput;
 import java.io.DataOutput;
@@ -32,6 +38,7 @@ import java.util.List;
  */
 public class BatchAlterJobPersistInfo implements Writable {
 
+    @SerializedName("l")
     private List<AlterJobV2> alterJobV2List;
 
     public BatchAlterJobPersistInfo(List<AlterJobV2> alterJobV2List) {
@@ -40,19 +47,20 @@ public class BatchAlterJobPersistInfo implements Writable {
 
     @Override
     public void write(DataOutput out) throws IOException {
-        out.writeInt(alterJobV2List.size());
-        for (AlterJobV2 alterJobV2 : alterJobV2List) {
-            alterJobV2.write(out);
-        }
+        Text.writeString(out, GsonUtils.GSON.toJson(this));
     }
 
     public static BatchAlterJobPersistInfo read(DataInput in) throws 
IOException {
-        int size = in.readInt();
-        List<AlterJobV2> alterJobV2List = new ArrayList<>();
-        for (int i = 0; i < size; i++) {
-            alterJobV2List.add(AlterJobV2.read(in));
+        if (Env.getCurrentEnvJournalVersion() < FeMetaVersion.VERSION_135) {
+            int size = in.readInt();
+            List<AlterJobV2> alterJobV2List = new ArrayList<>();
+            for (int i = 0; i < size; i++) {
+                alterJobV2List.add(AlterJobV2.read(in));
+            }
+            return new BatchAlterJobPersistInfo(alterJobV2List);
+        } else {
+            return GsonUtils.GSON.fromJson(Text.readString(in), 
BatchAlterJobPersistInfo.class);
         }
-        return new BatchAlterJobPersistInfo(alterJobV2List);
     }
 
     public List<AlterJobV2> getAlterJobV2List() {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/TableRef.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/TableRef.java
index 13821a510c6..3166d327d37 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/TableRef.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/TableRef.java
@@ -26,6 +26,7 @@ import org.apache.doris.catalog.Type;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.ErrorCode;
 import org.apache.doris.common.ErrorReport;
+import org.apache.doris.common.FeMetaVersion;
 import org.apache.doris.common.Pair;
 import org.apache.doris.common.UserException;
 import org.apache.doris.common.io.Text;
@@ -33,6 +34,7 @@ import org.apache.doris.common.io.Writable;
 import org.apache.doris.common.util.TimeUtils;
 import org.apache.doris.datasource.hive.HMSExternalTable;
 import org.apache.doris.datasource.hudi.HudiUtils;
+import org.apache.doris.persist.gson.GsonUtils;
 import org.apache.doris.rewrite.ExprRewriter;
 import org.apache.doris.rewrite.ExprRewriter.ClauseType;
 
@@ -40,6 +42,7 @@ import com.google.common.base.Joiner;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
+import com.google.gson.annotations.SerializedName;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
@@ -84,6 +87,7 @@ import java.util.regex.Matcher;
  */
 public class TableRef implements ParseNode, Writable {
     private static final Logger LOG = LogManager.getLogger(TableRef.class);
+    @SerializedName("n")
     protected TableName name;
     // Legal aliases of this table ref. Contains the explicit alias as its 
sole element if
     // there is one. Otherwise, contains the two implicit aliases. Implicit 
aliases are set
@@ -91,6 +95,7 @@ public class TableRef implements ParseNode, Writable {
     // analysis. By convention, for table refs with multiple implicit aliases, 
aliases_[0]
     // contains the fully-qualified implicit alias to ensure that aliases_[0] 
always
     // uniquely identifies this table ref regardless of whether it has an 
explicit alias.
+    @SerializedName("a")
     protected String[] aliases;
     protected List<Long> sampleTabletIds;
     // Indicates whether this table ref is given an explicit alias,
@@ -128,6 +133,7 @@ public class TableRef implements ParseNode, Writable {
     protected List<TupleId> correlatedTupleIds = Lists.newArrayList();
     // analysis output
     protected TupleDescriptor desc;
+    @SerializedName("p")
     private PartitionNames partitionNames = null;
     private ArrayList<String> joinHints;
     private ArrayList<String> sortHints;
@@ -973,23 +979,20 @@ public class TableRef implements ParseNode, Writable {
 
     @Override
     public void write(DataOutput out) throws IOException {
-        name.write(out);
-        if (partitionNames == null) {
-            out.writeBoolean(false);
-        } else {
-            out.writeBoolean(true);
-            partitionNames.write(out);
-        }
+        Text.writeString(out, GsonUtils.GSON.toJson(this));
+    }
 
-        if (hasExplicitAlias()) {
-            out.writeBoolean(true);
-            Text.writeString(out, getExplicitAlias());
+    public static TableRef read(DataInput in) throws IOException {
+        if (Env.getCurrentEnvJournalVersion() < FeMetaVersion.VERSION_135) {
+            TableRef ref = new TableRef();
+            ref.readFields(in);
+            return ref;
         } else {
-            out.writeBoolean(false);
+            return GsonUtils.GSON.fromJson(Text.readString(in), 
TableRef.class);
         }
     }
 
-    public void readFields(DataInput in) throws IOException {
+    private void readFields(DataInput in) throws IOException {
         name = new TableName();
         name.readFields(in);
         if (in.readBoolean()) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/backup/AbstractJob.java 
b/fe/fe-core/src/main/java/org/apache/doris/backup/AbstractJob.java
index 0df9155ab34..b29938eb9f4 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/backup/AbstractJob.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/backup/AbstractJob.java
@@ -24,6 +24,7 @@ import org.apache.doris.common.io.Writable;
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
+import com.google.gson.annotations.SerializedName;
 
 import java.io.DataInput;
 import java.io.DataOutput;
@@ -43,12 +44,14 @@ public abstract class AbstractJob implements Writable {
         BACKUP, RESTORE
     }
 
+    @SerializedName("t")
     protected JobType type;
 
     // must be set right before job's running
     protected Env env;
     // repo will be set at first run()
     protected Repository repo;
+    @SerializedName("rid")
     protected long repoId;
 
     /*
@@ -57,16 +60,23 @@ public abstract class AbstractJob implements Writable {
      * And each time this method is called, the snapshot tasks will be sent 
with (maybe) different
      * version and version hash. So we have to use different job id to 
identify the tasks in different batches.
      */
+    @SerializedName("jid")
     protected long jobId = -1;
 
+    @SerializedName("l")
     protected String label;
+    @SerializedName("dbid")
     protected long dbId;
+    @SerializedName("dbn")
     protected String dbName;
 
     protected Status status = Status.OK;
 
+    @SerializedName("ct")
     protected long createTime = -1;
+    @SerializedName("ft")
     protected long finishedTime = -1;
+    @SerializedName("to")
     protected long timeoutMs;
 
     // task signature -> <finished num / total num>
@@ -75,6 +85,7 @@ public abstract class AbstractJob implements Writable {
     protected boolean isTypeRead = false;
 
     // save err msg of tasks
+    @SerializedName("msg")
     protected Map<Long, String> taskErrMsg = Maps.newHashMap();
 
     protected AbstractJob(JobType type) {
@@ -207,6 +218,7 @@ public abstract class AbstractJob implements Writable {
         }
     }
 
+    @Deprecated
     public void readFields(DataInput in) throws IOException {
         if (!isTypeRead) {
             type = JobType.valueOf(Text.readString(in));
diff --git a/fe/fe-core/src/main/java/org/apache/doris/backup/BackupJob.java 
b/fe/fe-core/src/main/java/org/apache/doris/backup/BackupJob.java
index fc846bf1820..89b5ccccb6e 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/backup/BackupJob.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/backup/BackupJob.java
@@ -58,6 +58,7 @@ import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import com.google.gson.annotations.SerializedName;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
@@ -92,18 +93,24 @@ public class BackupJob extends AbstractJob {
     }
 
     // all objects which need backup
+    @SerializedName("ref")
     private List<TableRef> tableRefs = Lists.newArrayList();
 
+    @SerializedName("st")
     private BackupJobState state;
 
+    @SerializedName("sft")
     private long snapshotFinishedTime = -1;
+    @SerializedName("suft")
     private long snapshotUploadFinishedTime = -1;
 
     // save task id map to the backend it be executed
     private Map<Long, Long> unfinishedTaskIds = Maps.newConcurrentMap();
     // tablet id -> snapshot info
+    @SerializedName("si")
     private Map<Long, SnapshotInfo> snapshotInfos = Maps.newConcurrentMap();
     // save all related table[partition] info
+    @SerializedName("meta")
     private BackupMeta backupMeta;
     // job info file content
     private BackupJobInfo jobInfo;
@@ -112,9 +119,12 @@ public class BackupJob extends AbstractJob {
     // after job is done, this dir should be deleted
     private Path localJobDirPath = null;
     // save the local file path of meta info and job info file
+    @SerializedName("mifp")
     private String localMetaInfoFilePath = null;
+    @SerializedName("jifp")
     private String localJobInfoFilePath = null;
     // backup properties && table commit seq with table id
+    @SerializedName("prop")
     private Map<String, String> properties = Maps.newHashMap();
 
     private byte[] metaInfoBytes = null;
@@ -1033,10 +1043,11 @@ public class BackupJob extends AbstractJob {
 
         // table refs
         int size = in.readInt();
+        LOG.info("read {} tablerefs ", size);
+
         tableRefs = Lists.newArrayList();
         for (int i = 0; i < size; i++) {
-            TableRef tblRef = new TableRef();
-            tblRef.readFields(in);
+            TableRef tblRef = TableRef.read(in);
             tableRefs.add(tblRef);
         }
 
@@ -1048,14 +1059,16 @@ public class BackupJob extends AbstractJob {
 
         // snapshot info
         size = in.readInt();
+        LOG.info("read {} snapshotinfo ", size);
+
         for (int i = 0; i < size; i++) {
-            SnapshotInfo snapshotInfo = new SnapshotInfo();
-            snapshotInfo.readFields(in);
+            SnapshotInfo snapshotInfo = SnapshotInfo.read(in);
             snapshotInfos.put(snapshotInfo.getTabletId(), snapshotInfo);
         }
 
         // backup meta
         if (in.readBoolean()) {
+            LOG.info("read backup meta");
             backupMeta = BackupMeta.read(in);
         }
 
@@ -1071,6 +1084,8 @@ public class BackupJob extends AbstractJob {
         }
         // read properties
         size = in.readInt();
+        LOG.info("read {} property ", size);
+
         for (int i = 0; i < size; i++) {
             String key = Text.readString(in);
             String value = Text.readString(in);
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/backup/BackupJobInfo.java 
b/fe/fe-core/src/main/java/org/apache/doris/backup/BackupJobInfo.java
index aa127961e3d..554a21c4408 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/backup/BackupJobInfo.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/backup/BackupJobInfo.java
@@ -21,6 +21,7 @@ import org.apache.doris.analysis.BackupStmt.BackupContent;
 import org.apache.doris.analysis.PartitionNames;
 import org.apache.doris.analysis.TableRef;
 import org.apache.doris.backup.RestoreFileMapping.IdChain;
+import org.apache.doris.catalog.Env;
 import org.apache.doris.catalog.MaterializedIndex;
 import org.apache.doris.catalog.MaterializedIndex.IndexExtState;
 import org.apache.doris.catalog.OdbcCatalogResource;
@@ -34,9 +35,11 @@ import org.apache.doris.catalog.Tablet;
 import org.apache.doris.catalog.View;
 import org.apache.doris.common.Config;
 import org.apache.doris.common.FeConstants;
+import org.apache.doris.common.FeMetaVersion;
 import org.apache.doris.common.Version;
 import org.apache.doris.common.io.Text;
 import org.apache.doris.common.io.Writable;
+import org.apache.doris.persist.gson.GsonPostProcessable;
 import org.apache.doris.persist.gson.GsonUtils;
 import org.apache.doris.thrift.TNetworkAddress;
 
@@ -69,7 +72,7 @@ import java.util.Set;
  * It contains all content of a job info file.
  * It also be used to save the info of a restore job, such as alias of table 
and meta info file path
  */
-public class BackupJobInfo implements Writable {
+public class BackupJobInfo implements Writable, GsonPostProcessable {
     private static final Logger LOG = 
LogManager.getLogger(BackupJobInfo.class);
 
     @SerializedName("name")
@@ -133,6 +136,7 @@ public class BackupJobInfo implements Writable {
 
     // This map is used to save the table alias mapping info when processing a 
restore job.
     // origin -> alias
+    @SerializedName("tblalias")
     public Map<String, String> tblAlias = Maps.newHashMap();
 
     public long getBackupTime() {
@@ -756,11 +760,9 @@ public class BackupJobInfo implements Writable {
          * }
          */
         BackupJobInfo jobInfo = GsonUtils.GSON.fromJson(json, 
BackupJobInfo.class);
-        jobInfo.initBackupJobInfoAfterDeserialize();
         return jobInfo;
     }
 
-
     public void writeToFile(File jobInfoFile) throws FileNotFoundException {
         PrintWriter printWriter = new PrintWriter(jobInfoFile);
         try {
@@ -807,17 +809,21 @@ public class BackupJobInfo implements Writable {
     }
 
     public static BackupJobInfo read(DataInput in) throws IOException {
-        return BackupJobInfo.readFields(in);
+        if (Env.getCurrentEnvJournalVersion() < FeMetaVersion.VERSION_135) {
+            return BackupJobInfo.readFields(in);
+        }
+        String json = Text.readString(in);
+        return genFromJson(json);
     }
 
     @Override
     public void write(DataOutput out) throws IOException {
         Text.writeString(out, toJson(false));
-        out.writeInt(tblAlias.size());
-        for (Map.Entry<String, String> entry : tblAlias.entrySet()) {
-            Text.writeString(out, entry.getKey());
-            Text.writeString(out, entry.getValue());
-        }
+    }
+
+    @Override
+    public void gsonPostProcess() throws IOException {
+        initBackupJobInfoAfterDeserialize();
     }
 
     public static BackupJobInfo readFields(DataInput in) throws IOException {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/backup/BackupMeta.java 
b/fe/fe-core/src/main/java/org/apache/doris/backup/BackupMeta.java
index e22bb7f33ce..e9a1866a59b 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/backup/BackupMeta.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/backup/BackupMeta.java
@@ -21,6 +21,7 @@ import org.apache.doris.catalog.Resource;
 import org.apache.doris.catalog.Table;
 import org.apache.doris.common.io.Writable;
 import org.apache.doris.meta.MetaContext;
+import org.apache.doris.persist.gson.GsonPostProcessable;
 import org.apache.doris.persist.gson.GsonUtils;
 
 import com.google.common.collect.Maps;
@@ -37,13 +38,12 @@ import java.io.IOException;
 import java.util.List;
 import java.util.Map;
 
-public class BackupMeta implements Writable {
+public class BackupMeta implements Writable, GsonPostProcessable {
 
     // tbl name -> tbl
     @SerializedName(value = "tblNameMap")
     private Map<String, Table> tblNameMap = Maps.newHashMap();
     // tbl id -> tbl
-    @SerializedName(value = "tblIdMap")
     private Map<Long, Table> tblIdMap = Maps.newHashMap();
     // resource name -> resource
     @SerializedName(value = "resourceNameMap")
@@ -142,6 +142,13 @@ public class BackupMeta implements Writable {
         }
     }
 
+    @Override
+    public void gsonPostProcess() throws IOException {
+        for (Table table : tblNameMap.values()) {
+            tblIdMap.put(table.getId(), table);
+        }
+    }
+
     public String toJson() {
         return GsonUtils.GSON.toJson(this);
     }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/backup/RestoreFileMapping.java 
b/fe/fe-core/src/main/java/org/apache/doris/backup/RestoreFileMapping.java
index 07ddf6844dc..4bb791d84d7 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/backup/RestoreFileMapping.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/backup/RestoreFileMapping.java
@@ -17,11 +17,16 @@
 
 package org.apache.doris.backup;
 
+import org.apache.doris.catalog.Env;
+import org.apache.doris.common.FeMetaVersion;
+import org.apache.doris.common.io.Text;
 import org.apache.doris.common.io.Writable;
+import org.apache.doris.persist.gson.GsonUtils;
 
 import com.google.common.base.Joiner;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
+import com.google.gson.annotations.SerializedName;
 
 import java.io.DataInput;
 import java.io.DataOutput;
@@ -30,8 +35,9 @@ import java.util.Map;
 
 public class RestoreFileMapping implements Writable {
 
-    public static class IdChain implements Writable {
+    public static class IdChain {
         // tblId, partId, idxId, tabletId, replicaId
+        @SerializedName("c")
         private Long[] chain;
 
         private IdChain() {
@@ -98,14 +104,6 @@ public class RestoreFileMapping implements Writable {
             return code;
         }
 
-        @Override
-        public void write(DataOutput out) throws IOException {
-            out.writeInt(chain.length);
-            for (Long id : chain) {
-                out.writeLong(id);
-            }
-        }
-
         public void readFields(DataInput in) throws IOException {
             int size = in.readInt();
             chain = new Long[size];
@@ -122,8 +120,10 @@ public class RestoreFileMapping implements Writable {
     }
 
     // catalog ids -> repository ids
+    @SerializedName("m")
     private Map<IdChain, IdChain> mapping = Maps.newHashMap();
     // tablet id -> is overwrite
+    @SerializedName("o")
     private Map<Long, Boolean> overwriteMap = Maps.newHashMap();
 
     public RestoreFileMapping() {
@@ -151,9 +151,13 @@ public class RestoreFileMapping implements Writable {
     }
 
     public static RestoreFileMapping read(DataInput in) throws IOException {
-        RestoreFileMapping mapping = new RestoreFileMapping();
-        mapping.readFields(in);
-        return mapping;
+        if (Env.getCurrentEnvJournalVersion() < FeMetaVersion.VERSION_135) {
+            RestoreFileMapping mapping = new RestoreFileMapping();
+            mapping.readFields(in);
+            return mapping;
+        } else {
+            return GsonUtils.GSON.fromJson(Text.readString(in), 
RestoreFileMapping.class);
+        }
     }
 
     public void clear() {
@@ -163,17 +167,7 @@ public class RestoreFileMapping implements Writable {
 
     @Override
     public void write(DataOutput out) throws IOException {
-        out.writeInt(mapping.size());
-        for (Map.Entry<IdChain, IdChain> entry : mapping.entrySet()) {
-            entry.getKey().write(out);
-            entry.getValue().write(out);
-        }
-
-        out.writeInt(overwriteMap.size());
-        for (Map.Entry<Long, Boolean> entry : overwriteMap.entrySet()) {
-            out.writeLong(entry.getKey());
-            out.writeBoolean(entry.getValue());
-        }
+        Text.writeString(out, GsonUtils.GSON.toJson(this));
     }
 
     public void readFields(DataInput in) throws IOException {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/backup/RestoreJob.java 
b/fe/fe-core/src/main/java/org/apache/doris/backup/RestoreJob.java
index 99f5f028e6e..903e2ef95ef 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/backup/RestoreJob.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/backup/RestoreJob.java
@@ -66,6 +66,8 @@ import org.apache.doris.common.util.DynamicPartitionUtil;
 import org.apache.doris.common.util.PropertyAnalyzer;
 import org.apache.doris.common.util.TimeUtils;
 import org.apache.doris.datasource.property.S3ClientBEProperties;
+import org.apache.doris.persist.gson.GsonPostProcessable;
+// import org.apache.doris.persist.gson.GsonUtils;
 import org.apache.doris.resource.Tag;
 import org.apache.doris.task.AgentBatchTask;
 import org.apache.doris.task.AgentTask;
@@ -93,6 +95,7 @@ import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Multimap;
 import com.google.common.collect.Table.Cell;
+import com.google.gson.annotations.SerializedName;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
@@ -106,7 +109,7 @@ import java.util.Set;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
-public class RestoreJob extends AbstractJob {
+public class RestoreJob extends AbstractJob implements GsonPostProcessable {
     private static final String PROP_RESERVE_REPLICA = "reserve_replica";
     private static final String PROP_RESERVE_DYNAMIC_PARTITION_ENABLE = 
"reserve_dynamic_partition_enable";
     private static final String PROP_IS_BEING_SYNCED = 
PropertyAnalyzer.PROPERTIES_IS_BEING_SYNCED;
@@ -129,21 +132,31 @@ public class RestoreJob extends AbstractJob {
     }
     // CHECKSTYLE ON
 
+    @SerializedName("bts")
     private String backupTimestamp;
 
+    @SerializedName("j")
     private BackupJobInfo jobInfo;
+    @SerializedName("al")
     private boolean allowLoad;
 
+    @SerializedName("st")
     private RestoreJobState state;
 
+    @SerializedName("meta")
     private BackupMeta backupMeta;
 
+    @SerializedName("fm")
     private RestoreFileMapping fileMapping = new RestoreFileMapping();
 
+    @SerializedName("mpt")
     private long metaPreparedTime = -1;
+    @SerializedName("sft")
     private long snapshotFinishedTime = -1;
+    @SerializedName("dft")
     private long downloadFinishedTime = -1;
 
+    @SerializedName("ra")
     private ReplicaAllocation replicaAlloc;
 
     private boolean reserveReplica = false;
@@ -151,14 +164,19 @@ public class RestoreJob extends AbstractJob {
 
     // this 2 members is to save all newly restored objs
     // tbl name -> part
+    @SerializedName("rp")
     private List<Pair<String, Partition>> restoredPartitions = 
Lists.newArrayList();
+    @SerializedName("rt")
     private List<Table> restoredTbls = Lists.newArrayList();
+    @SerializedName("rr")
     private List<Resource> restoredResources = Lists.newArrayList();
 
     // save all restored partitions' version info which are already exist in 
catalog
     // table id -> partition id -> (version, version hash)
+    @SerializedName("rvi")
     private com.google.common.collect.Table<Long, Long, Long> 
restoredVersionInfo = HashBasedTable.create();
     // tablet id->(be id -> snapshot info)
+    @SerializedName("si")
     private com.google.common.collect.Table<Long, Long, SnapshotInfo> 
snapshotInfos = HashBasedTable.create();
 
     private Map<Long, Long> unfinishedSignatureToId = Maps.newConcurrentMap();
@@ -175,6 +193,7 @@ public class RestoreJob extends AbstractJob {
     private boolean isBeingSynced = false;
 
     // restore properties
+    @SerializedName("prop")
     private Map<String, String> properties = Maps.newHashMap();
 
     public RestoreJob() {
@@ -2078,12 +2097,6 @@ public class RestoreJob extends AbstractJob {
         }
     }
 
-    public static RestoreJob read(DataInput in) throws IOException {
-        RestoreJob job = new RestoreJob();
-        job.readFields(in);
-        return job;
-    }
-
     @Override
     public void write(DataOutput out) throws IOException {
         super.write(out);
@@ -2157,6 +2170,13 @@ public class RestoreJob extends AbstractJob {
         }
     }
 
+    public static RestoreJob read(DataInput in) throws IOException {
+        RestoreJob job = new RestoreJob();
+        job.readFields(in);
+        return job;
+    }
+
+    @Deprecated
     @Override
     public void readFields(DataInput in) throws IOException {
         super.readFields(in);
@@ -2238,6 +2258,13 @@ public class RestoreJob extends AbstractJob {
         isBeingSynced = 
Boolean.parseBoolean(properties.get(PROP_IS_BEING_SYNCED));
     }
 
+    @Override
+    public void gsonPostProcess() throws IOException {
+        reserveReplica = 
Boolean.parseBoolean(properties.get(PROP_RESERVE_REPLICA));
+        reserveDynamicPartitionEnable = 
Boolean.parseBoolean(properties.get(PROP_RESERVE_DYNAMIC_PARTITION_ENABLE));
+        isBeingSynced = 
Boolean.parseBoolean(properties.get(PROP_IS_BEING_SYNCED));
+    }
+
     @Override
     public String toString() {
         StringBuilder sb = new StringBuilder(super.toString());
diff --git a/fe/fe-core/src/main/java/org/apache/doris/backup/SnapshotInfo.java 
b/fe/fe-core/src/main/java/org/apache/doris/backup/SnapshotInfo.java
index 60847e822dc..1d70babb98f 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/backup/SnapshotInfo.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/backup/SnapshotInfo.java
@@ -17,11 +17,15 @@
 
 package org.apache.doris.backup;
 
+import org.apache.doris.catalog.Env;
+import org.apache.doris.common.FeMetaVersion;
 import org.apache.doris.common.io.Text;
 import org.apache.doris.common.io.Writable;
+import org.apache.doris.persist.gson.GsonUtils;
 
 import com.google.common.base.Joiner;
 import com.google.common.collect.Lists;
+import com.google.gson.annotations.SerializedName;
 
 import java.io.DataInput;
 import java.io.DataOutput;
@@ -29,19 +33,28 @@ import java.io.IOException;
 import java.util.List;
 
 public class SnapshotInfo implements Writable {
+    @SerializedName("db")
     private long dbId;
+    @SerializedName("tbl")
     private long tblId;
+    @SerializedName("p")
     private long partitionId;
+    @SerializedName("ind")
     private long indexId;
+    @SerializedName("tab")
     private long tabletId;
+    @SerializedName("be")
     private long beId;
+    @SerializedName("sh")
     private int schemaHash;
     // eg: /path/to/your/be/data/snapshot/20180410102311.0.86400/
+    @SerializedName("path")
     private String path;
     // eg:
     // 10006_0_1_0_0.dat
     // 10006_2_2_0_0.idx
     // 10006.hdr
+    @SerializedName("f")
     private List<String> files = Lists.newArrayList();
 
     public SnapshotInfo() {
@@ -107,26 +120,19 @@ public class SnapshotInfo implements Writable {
     }
 
     public static SnapshotInfo read(DataInput in) throws IOException {
-        SnapshotInfo info = new SnapshotInfo();
-        info.readFields(in);
-        return info;
+        if (Env.getCurrentEnvJournalVersion() < FeMetaVersion.VERSION_135) {
+            SnapshotInfo info = new SnapshotInfo();
+            info.readFields(in);
+            return info;
+        } else {
+            String json = Text.readString(in);
+            return GsonUtils.GSON.fromJson(json, SnapshotInfo.class);
+        }
     }
 
     @Override
     public void write(DataOutput out) throws IOException {
-        out.writeLong(dbId);
-        out.writeLong(tblId);
-        out.writeLong(partitionId);
-        out.writeLong(indexId);
-        out.writeLong(tabletId);
-        out.writeLong(beId);
-        out.writeInt(schemaHash);
-        Text.writeString(out, path);
-
-        out.writeInt(files.size());
-        for (String file : files) {
-            Text.writeString(out, file);
-        }
+        Text.writeString(out, GsonUtils.GSON.toJson(this));
     }
 
     public void readFields(DataInput in) throws IOException {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionSearchDesc.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionSearchDesc.java
index 3eed1ab4996..6e87e83b649 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionSearchDesc.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/FunctionSearchDesc.java
@@ -18,7 +18,12 @@
 package org.apache.doris.catalog;
 
 import org.apache.doris.analysis.FunctionName;
+import org.apache.doris.common.FeMetaVersion;
+import org.apache.doris.common.io.Text;
 import org.apache.doris.common.io.Writable;
+import org.apache.doris.persist.gson.GsonUtils;
+
+import com.google.gson.annotations.SerializedName;
 
 import java.io.DataInput;
 import java.io.DataOutput;
@@ -26,8 +31,11 @@ import java.io.IOException;
 
 // Used to search a function
 public class FunctionSearchDesc implements Writable {
+    @SerializedName("n")
     private FunctionName name;
+    @SerializedName("t")
     private Type[] argTypes;
+    @SerializedName("isV")
     private boolean isVariadic;
 
     private FunctionSearchDesc() {}
@@ -93,15 +101,10 @@ public class FunctionSearchDesc implements Writable {
 
     @Override
     public void write(DataOutput out) throws IOException {
-        name.write(out);
-        // write args
-        out.writeShort(argTypes.length);
-        for (Type type : argTypes) {
-            ColumnType.write(out, type);
-        }
-        out.writeBoolean(isVariadic);
+        Text.writeString(out, GsonUtils.GSON.toJson(this));
     }
 
+    @Deprecated
     public void readFields(DataInput in) throws IOException {
         name = FunctionName.read(in);
         // read args
@@ -114,8 +117,12 @@ public class FunctionSearchDesc implements Writable {
     }
 
     public static FunctionSearchDesc read(DataInput input) throws IOException {
-        FunctionSearchDesc function = new FunctionSearchDesc();
-        function.readFields(input);
-        return function;
+        if (Env.getCurrentEnvJournalVersion() < FeMetaVersion.VERSION_135) {
+            FunctionSearchDesc function = new FunctionSearchDesc();
+            function.readFields(input);
+            return function;
+        } else {
+            return GsonUtils.GSON.fromJson(Text.readString(input), 
FunctionSearchDesc.class);
+        }
     }
 }
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/MTMV.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/MTMV.java
index 1b4a8e7063e..f238cf2f1ab 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/MTMV.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/MTMV.java
@@ -20,6 +20,7 @@ package org.apache.doris.catalog;
 import org.apache.doris.analysis.PartitionKeyDesc;
 import org.apache.doris.catalog.OlapTableFactory.MTMVParams;
 import org.apache.doris.common.AnalysisException;
+import org.apache.doris.common.FeMetaVersion;
 import org.apache.doris.common.Pair;
 import org.apache.doris.common.io.Text;
 import org.apache.doris.common.util.PropertyAnalyzer;
@@ -41,10 +42,14 @@ import org.apache.doris.mtmv.MTMVRefreshSnapshot;
 import org.apache.doris.mtmv.MTMVRelation;
 import org.apache.doris.mtmv.MTMVStatus;
 import org.apache.doris.persist.gson.GsonUtils;
+import org.apache.doris.persist.gson.GsonUtils134;
 import org.apache.doris.qe.ConnectContext;
 
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
+//import com.google.gson.JsonElement;
+//import com.google.gson.JsonObject;
+//import com.google.gson.JsonParser;
 import com.google.gson.annotations.SerializedName;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.logging.log4j.LogManager;
@@ -453,7 +458,13 @@ public class MTMV extends OlapTable {
     @Override
     public void readFields(DataInput in) throws IOException {
         super.readFields(in);
-        MTMV materializedView = GsonUtils.GSON.fromJson(Text.readString(in), 
this.getClass());
+        MTMV materializedView = null;
+        if (Env.getCurrentEnvJournalVersion() < FeMetaVersion.VERSION_135) {
+            materializedView = GsonUtils134.GSON.fromJson(Text.readString(in), 
this.getClass());
+        } else {
+            materializedView = GsonUtils.GSON.fromJson(Text.readString(in), 
this.getClass());
+        }
+
         refreshInfo = materializedView.refreshInfo;
         querySql = materializedView.querySql;
         status = materializedView.status;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/persist/gson/GsonUtils.java 
b/fe/fe-core/src/main/java/org/apache/doris/persist/gson/GsonUtils.java
index 482118bb4ee..79775a2ef24 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/persist/gson/GsonUtils.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/persist/gson/GsonUtils.java
@@ -58,19 +58,35 @@ import org.apache.doris.analysis.StringLiteral;
 import org.apache.doris.analysis.StructLiteral;
 import org.apache.doris.analysis.TimestampArithmeticExpr;
 import org.apache.doris.analysis.VirtualSlotRef;
+import org.apache.doris.backup.BackupJob;
+import org.apache.doris.backup.RestoreJob;
 import org.apache.doris.catalog.AggStateType;
+import org.apache.doris.catalog.AnyElementType;
+import org.apache.doris.catalog.AnyStructType;
+import org.apache.doris.catalog.AnyType;
 import org.apache.doris.catalog.ArrayType;
+import org.apache.doris.catalog.BrokerTable;
 import org.apache.doris.catalog.DatabaseIf;
 import org.apache.doris.catalog.DistributionInfo;
 import org.apache.doris.catalog.Env;
 import org.apache.doris.catalog.EsResource;
+import org.apache.doris.catalog.EsTable;
+import org.apache.doris.catalog.FunctionGenTable;
 import org.apache.doris.catalog.HMSResource;
 import org.apache.doris.catalog.HashDistributionInfo;
 import org.apache.doris.catalog.HdfsResource;
+import org.apache.doris.catalog.HiveTable;
+import org.apache.doris.catalog.InlineView;
 import org.apache.doris.catalog.JdbcResource;
+import org.apache.doris.catalog.JdbcTable;
 import org.apache.doris.catalog.ListPartitionInfo;
+import org.apache.doris.catalog.MTMV;
 import org.apache.doris.catalog.MapType;
+import org.apache.doris.catalog.MultiRowType;
+import org.apache.doris.catalog.MysqlDBTable;
+import org.apache.doris.catalog.MysqlTable;
 import org.apache.doris.catalog.OdbcCatalogResource;
+import org.apache.doris.catalog.OdbcTable;
 import org.apache.doris.catalog.OlapTable;
 import org.apache.doris.catalog.Partition;
 import org.apache.doris.catalog.PartitionInfo;
@@ -81,11 +97,15 @@ import org.apache.doris.catalog.Replica;
 import org.apache.doris.catalog.Resource;
 import org.apache.doris.catalog.S3Resource;
 import org.apache.doris.catalog.ScalarType;
+import org.apache.doris.catalog.SchemaTable;
 import org.apache.doris.catalog.SinglePartitionInfo;
 import org.apache.doris.catalog.SparkResource;
 import org.apache.doris.catalog.StructType;
 import org.apache.doris.catalog.TableIf;
 import org.apache.doris.catalog.Tablet;
+import org.apache.doris.catalog.TemplateType;
+import org.apache.doris.catalog.VariantType;
+import org.apache.doris.catalog.View;
 import org.apache.doris.catalog.constraint.Constraint;
 import org.apache.doris.catalog.constraint.ForeignKeyConstraint;
 import org.apache.doris.catalog.constraint.PrimaryKeyConstraint;
@@ -139,7 +159,13 @@ import org.apache.doris.datasource.test.TestExternalTable;
 import 
org.apache.doris.datasource.trinoconnector.TrinoConnectorExternalCatalog;
 import 
org.apache.doris.datasource.trinoconnector.TrinoConnectorExternalDatabase;
 import org.apache.doris.datasource.trinoconnector.TrinoConnectorExternalTable;
-import org.apache.doris.job.base.AbstractJob;
+import org.apache.doris.fs.remote.BrokerFileSystem;
+import org.apache.doris.fs.remote.ObjFileSystem;
+import org.apache.doris.fs.remote.RemoteFileSystem;
+import org.apache.doris.fs.remote.S3FileSystem;
+import org.apache.doris.fs.remote.dfs.DFSFileSystem;
+import org.apache.doris.fs.remote.dfs.JFSFileSystem;
+import org.apache.doris.fs.remote.dfs.OFSFileSystem;
 import org.apache.doris.job.extensions.insert.InsertJob;
 import org.apache.doris.job.extensions.mtmv.MTMVJob;
 import org.apache.doris.load.loadv2.LoadJob.LoadJobStateUpdateInfo;
@@ -236,7 +262,13 @@ public class GsonUtils {
             .registerSubtype(ArrayType.class, ArrayType.class.getSimpleName())
             .registerSubtype(MapType.class, MapType.class.getSimpleName())
             .registerSubtype(StructType.class, 
StructType.class.getSimpleName())
-            .registerSubtype(AggStateType.class, 
AggStateType.class.getSimpleName());
+            .registerSubtype(AggStateType.class, 
AggStateType.class.getSimpleName())
+            .registerSubtype(AnyElementType.class, 
AnyElementType.class.getSimpleName())
+            .registerSubtype(AnyStructType.class, 
AnyStructType.class.getSimpleName())
+            .registerSubtype(AnyType.class, AnyType.class.getSimpleName())
+            .registerSubtype(MultiRowType.class, 
MultiRowType.class.getSimpleName())
+            .registerSubtype(TemplateType.class, 
TemplateType.class.getSimpleName())
+            .registerSubtype(VariantType.class, 
VariantType.class.getSimpleName());
 
     // runtime adapter for class "Expr"
     private static final 
RuntimeTypeAdapterFactory<org.apache.doris.analysis.Expr> exprAdapterFactory
@@ -373,10 +405,11 @@ public class GsonUtils {
             RuntimeTypeAdapterFactory.of(
                             AbstractDataSourceProperties.class, "clazz")
                     .registerSubtype(KafkaDataSourceProperties.class, 
KafkaDataSourceProperties.class.getSimpleName());
-    private static RuntimeTypeAdapterFactory<AbstractJob> 
jobExecutorRuntimeTypeAdapterFactory =
-            RuntimeTypeAdapterFactory.of(AbstractJob.class, "clazz")
-                    .registerSubtype(InsertJob.class, 
InsertJob.class.getSimpleName())
-                    .registerSubtype(MTMVJob.class, 
MTMVJob.class.getSimpleName());
+    private static 
RuntimeTypeAdapterFactory<org.apache.doris.job.base.AbstractJob>
+            jobExecutorRuntimeTypeAdapterFactory
+                    = 
RuntimeTypeAdapterFactory.of(org.apache.doris.job.base.AbstractJob.class, 
"clazz")
+                            .registerSubtype(InsertJob.class, 
InsertJob.class.getSimpleName())
+                            .registerSubtype(MTMVJob.class, 
MTMVJob.class.getSimpleName());
 
     private static RuntimeTypeAdapterFactory<MTMVSnapshotIf> 
mtmvSnapshotTypeAdapterFactory =
             RuntimeTypeAdapterFactory.of(MTMVSnapshotIf.class, "clazz")
@@ -412,7 +445,19 @@ public class GsonUtils {
             .registerSubtype(ExternalInfoSchemaTable.class, 
ExternalInfoSchemaTable.class.getSimpleName())
             .registerSubtype(ExternalMysqlTable.class, 
ExternalMysqlTable.class.getSimpleName())
             .registerSubtype(TrinoConnectorExternalTable.class, 
TrinoConnectorExternalTable.class.getSimpleName())
-            .registerSubtype(TestExternalTable.class, 
TestExternalTable.class.getSimpleName());
+            .registerSubtype(TestExternalTable.class, 
TestExternalTable.class.getSimpleName())
+            .registerSubtype(BrokerTable.class, 
BrokerTable.class.getSimpleName())
+            .registerSubtype(EsTable.class, EsTable.class.getSimpleName())
+            .registerSubtype(FunctionGenTable.class, 
FunctionGenTable.class.getSimpleName())
+            .registerSubtype(HiveTable.class, HiveTable.class.getSimpleName())
+            .registerSubtype(InlineView.class, 
InlineView.class.getSimpleName())
+            .registerSubtype(JdbcTable.class, JdbcTable.class.getSimpleName())
+            .registerSubtype(MTMV.class, MTMV.class.getSimpleName())
+            .registerSubtype(MysqlDBTable.class, 
MysqlDBTable.class.getSimpleName())
+            .registerSubtype(MysqlTable.class, 
MysqlTable.class.getSimpleName())
+            .registerSubtype(OdbcTable.class, OdbcTable.class.getSimpleName())
+            .registerSubtype(SchemaTable.class, 
SchemaTable.class.getSimpleName())
+            .registerSubtype(View.class, View.class.getSimpleName());
 
     // runtime adapter for class "PartitionInfo"
     private static RuntimeTypeAdapterFactory<PartitionInfo> 
partitionInfoTypeAdapterFactory
@@ -471,6 +516,21 @@ public class GsonUtils {
             .registerDefaultSubtype(RoutineLoadProgress.class)
             .registerSubtype(KafkaProgress.class, 
KafkaProgress.class.getSimpleName());
 
+    private static RuntimeTypeAdapterFactory<RemoteFileSystem> 
remoteFileSystemTypeAdapterFactory
+            = RuntimeTypeAdapterFactory.of(RemoteFileSystem.class, "clazz")
+            .registerSubtype(BrokerFileSystem.class, 
BrokerFileSystem.class.getSimpleName())
+            .registerSubtype(DFSFileSystem.class, 
DFSFileSystem.class.getSimpleName())
+            .registerSubtype(JFSFileSystem.class, 
JFSFileSystem.class.getSimpleName())
+            .registerSubtype(OFSFileSystem.class, 
OFSFileSystem.class.getSimpleName())
+            .registerSubtype(ObjFileSystem.class, 
ObjFileSystem.class.getSimpleName())
+            .registerSubtype(S3FileSystem.class, 
S3FileSystem.class.getSimpleName());
+
+    private static 
RuntimeTypeAdapterFactory<org.apache.doris.backup.AbstractJob>
+            jobBackupTypeAdapterFactory
+                    = 
RuntimeTypeAdapterFactory.of(org.apache.doris.backup.AbstractJob.class, "clazz")
+                    .registerSubtype(BackupJob.class, 
BackupJob.class.getSimpleName())
+                    .registerSubtype(RestoreJob.class, 
RestoreJob.class.getSimpleName());
+
     // the builder of GSON instance.
     // Add any other adapters if necessary.
     private static final GsonBuilder GSON_BUILDER = new 
GsonBuilder().addSerializationExclusionStrategy(
@@ -501,6 +561,8 @@ public class GsonUtils {
             .registerTypeAdapterFactory(constraintTypeAdapterFactory)
             .registerTypeAdapterFactory(txnCommitAttachmentTypeAdapterFactory)
             .registerTypeAdapterFactory(routineLoadTypeAdapterFactory)
+            .registerTypeAdapterFactory(remoteFileSystemTypeAdapterFactory)
+            .registerTypeAdapterFactory(jobBackupTypeAdapterFactory)
             .registerTypeAdapter(ImmutableMap.class, new 
ImmutableMapDeserializer())
             .registerTypeAdapter(AtomicBoolean.class, new 
AtomicBooleanAdapter())
             .registerTypeAdapter(PartitionKey.class, new 
PartitionKey.PartitionKeySerializer())
@@ -656,7 +718,6 @@ public class GsonUtils {
         private static final String EXPR_PROP = "expr";
 
         public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
-
             final Class<T> rawType = (Class<T>) type.getRawType();
             final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, 
type);
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/persist/gson/GsonUtils.java 
b/fe/fe-core/src/main/java/org/apache/doris/persist/gson/GsonUtils134.java
similarity index 99%
copy from fe/fe-core/src/main/java/org/apache/doris/persist/gson/GsonUtils.java
copy to fe/fe-core/src/main/java/org/apache/doris/persist/gson/GsonUtils134.java
index 482118bb4ee..1359bb170df 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/persist/gson/GsonUtils.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/persist/gson/GsonUtils134.java
@@ -225,7 +225,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
  * You need implement a class to implements JsonSerializer and 
JsonDeserializer, and register it to GSON_BUILDER.
  * See the following "GuavaTableAdapter" and "GuavaMultimapAdapter" for 
example.
  */
-public class GsonUtils {
+public class GsonUtils134 {
 
     // runtime adapter for class "Type"
     private static RuntimeTypeAdapterFactory<org.apache.doris.catalog.Type> 
columnTypeAdapterFactory
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/persist/gson/RuntimeTypeAdapterFactory.java
 
b/fe/fe-core/src/main/java/org/apache/doris/persist/gson/RuntimeTypeAdapterFactory.java
index 15270bc85bb..ee780f0de1b 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/persist/gson/RuntimeTypeAdapterFactory.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/persist/gson/RuntimeTypeAdapterFactory.java
@@ -32,6 +32,7 @@ import com.google.gson.stream.JsonReader;
 import com.google.gson.stream.JsonWriter;
 
 import java.io.IOException;
+import java.lang.reflect.Modifier;
 import java.util.LinkedHashMap;
 import java.util.Map;
 
@@ -282,7 +283,9 @@ public final class RuntimeTypeAdapterFactory<T> implements 
TypeAdapterFactory {
     }
 
     public <R> TypeAdapter<R> create(Gson gson, TypeToken<R> type) {
-        if (type.getRawType() != baseType && 
!subtypeToLabel.containsKey(type.getRawType())) {
+        if (baseType != type.getRawType() && 
!subtypeToLabel.containsKey(type.getRawType())
+                && !(Modifier.isAbstract(type.getRawType().getModifiers())
+                     && baseType.isAssignableFrom(type.getRawType()))) {
             return null;
         }
 
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/backup/BackupJobTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/backup/BackupJobTest.java
index 4e0eecda1fa..68f02e8eee8 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/backup/BackupJobTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/backup/BackupJobTest.java
@@ -26,6 +26,7 @@ import org.apache.doris.catalog.Database;
 import org.apache.doris.catalog.Env;
 import org.apache.doris.catalog.FsBroker;
 import org.apache.doris.catalog.OlapTable;
+import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.Config;
 import org.apache.doris.common.FeConstants;
 import org.apache.doris.common.jmockit.Deencapsulation;
@@ -58,6 +59,8 @@ import org.junit.Before;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.FileVisitOption;
@@ -353,4 +356,36 @@ public class BackupJobTest {
         Assert.assertEquals(Status.ErrCode.NOT_FOUND, 
job.getStatus().getErrCode());
         Assert.assertEquals(BackupJobState.CANCELLED, job.getState());
     }
+
+    @Test
+    public void testSerialization() throws IOException, AnalysisException {
+        // 1. Write objects to file
+        final Path path = Files.createTempFile("backupJob", "tmp");
+        DataOutputStream out = new 
DataOutputStream(Files.newOutputStream(path));
+
+        List<TableRef> tableRefs = Lists.newArrayList();
+        tableRefs.add(
+                new TableRef(new 
TableName(InternalCatalog.INTERNAL_CATALOG_NAME, UnitTestUtil.DB_NAME, 
UnitTestUtil.TABLE_NAME),
+                        null));
+        job = new BackupJob("label", dbId, UnitTestUtil.DB_NAME, tableRefs, 
13600 * 1000, BackupStmt.BackupContent.ALL,
+            env, repo.getId());
+
+        job.write(out);
+        out.flush();
+        out.close();
+
+        // 2. Read objects from file
+        DataInputStream in = new DataInputStream(Files.newInputStream(path));
+
+        BackupJob job2 = BackupJob.read(in);
+
+        Assert.assertEquals(job.getJobId(), job2.getJobId());
+        Assert.assertEquals(job.getDbId(), job2.getDbId());
+        Assert.assertEquals(job.getCreateTime(), job2.getCreateTime());
+        Assert.assertEquals(job.getType(), job2.getType());
+
+        // 3. delete files
+        in.close();
+        Files.delete(path);
+    }
 }
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/backup/RestoreJobTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/backup/RestoreJobTest.java
index ff60a6e8b90..71cad0438c9 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/backup/RestoreJobTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/backup/RestoreJobTest.java
@@ -51,9 +51,15 @@ import mockit.Injectable;
 import mockit.Mock;
 import mockit.MockUp;
 import mockit.Mocked;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
@@ -276,4 +282,28 @@ public class RestoreJobTest {
         System.out.println("tbl signature: " + 
tbl.getSignature(BackupHandler.SIGNATURE_VERSION, partNames));
     }
 
+    @Test
+    public void testSerialization() throws IOException, AnalysisException {
+        // 1. Write objects to file
+        final Path path = Files.createTempFile("restoreJob", "tmp");
+        DataOutputStream out = new 
DataOutputStream(Files.newOutputStream(path));
+
+        job.write(out);
+        out.flush();
+        out.close();
+
+        // 2. Read objects from file
+        DataInputStream in = new DataInputStream(Files.newInputStream(path));
+
+        RestoreJob job2 = RestoreJob.read(in);
+
+        Assert.assertEquals(job.getJobId(), job2.getJobId());
+        Assert.assertEquals(job.getDbId(), job2.getDbId());
+        Assert.assertEquals(job.getCreateTime(), job2.getCreateTime());
+        Assert.assertEquals(job.getType(), job2.getType());
+
+        // 3. delete files
+        in.close();
+        Files.delete(path);
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to