Code review comment: Like above, add more comments about this.  partitionRefTableExprs is not serialized for gson and only serializes the expression-sql instead which I think is more compatible for upgrade/downgrade.  so need to recover it in gsonPostProcess phase, expressionSql  is only parseSqlToExpr and no analyzed and needs to check expression's type here to make it more compatible for further usage.

Code under review:
public void gsonPostProcess() throws IOException {
        super.gsonPostProcess();
        
        if (!(partitionInfo instanceof ExpressionRangePartitionInfo)) {
            return;
        }
        ExpressionRangePartitionInfo expressionRangePartitionInfo = (ExpressionRangePartitionInfo) partitionInfo;
        Type partitionColType = expressionRangePartitionInfo.getPartitionColumns().get(0).getType();

        
        partitionRefTableExprs = new ArrayList<>();
        if (serializedPartitionRefTableExprs != null) {
            for (GsonUtils.ExpressionSerializedObject expressionSql : serializedPartitionRefTableExprs) {
                if (expressionSql != null) {
                    Expr partitionExpr = SqlParser.parseSqlToExpr(expressionSql.expressionSql, SqlModeHelper.MODE_DEFAULT);
                    if (partitionExpr.getType() == Type.INVALID) {
                        partitionExpr.setType(partitionColType);
                    }
                    partitionRefTableExprs.add(partitionExpr);
                }
            }
        }

        
        partitionExprMaps = Maps.newHashMap();
        if (serializedPartitionExprMaps != null) {
            for (Map.Entry<GsonUtils.ExpressionSerializedObject, GsonUtils.ExpressionSerializedObject> entry :
                    serializedPartitionExprMaps.entrySet()) {
                if (entry.getKey() != null && entry.getValue() != null) {
                    Expr partitionExpr = SqlParser.parseSqlToExpr(entry.getKey().expressionSql, SqlModeHelper.MODE_DEFAULT);
                    if (partitionExpr.getType() == Type.INVALID) {
                        partitionExpr.setType(partitionColType);
                    }
                    SlotRef partitionSlotRef = getMvPartitionSlotRef(partitionExpr);
                    partitionExprMaps.put(partitionExpr, partitionSlotRef);
                }
            }
        } else if (!partitionRefTableExprs.isEmpty()) {
            
            Expr partitionExpr = partitionRefTableExprs.get(0);
            SlotRef partitionSlotRef = getMvPartitionSlotRef(partitionExpr);
            partitionExprMaps.put(partitionExpr, partitionSlotRef);
        }
    }

Line commented on: if (partitionExpr.getType() == Type.INVALID) {

Revised code:
public void gsonPostProcess() throws IOException {
        super.gsonPostProcess();
        
        if (!(partitionInfo instanceof ExpressionRangePartitionInfo)) {
            return;
        }
        ExpressionRangePartitionInfo expressionRangePartitionInfo = (ExpressionRangePartitionInfo) partitionInfo;
        
        Preconditions.checkState(expressionRangePartitionInfo.getPartitionColumns().size() == 1);
        Column partitionCol = expressionRangePartitionInfo.getPartitionColumns().get(0);

        
        partitionRefTableExprs = new ArrayList<>();
        partitionExprMaps = Maps.newHashMap();
        if (serializedPartitionRefTableExprs != null) {
            for (GsonUtils.ExpressionSerializedObject serializedObject : serializedPartitionRefTableExprs) {
                Expr partitionExpr = parsePartitionExpr(serializedObject.expressionSql, partitionCol);
                if (partitionExpr == null) {
                    LOG.warn("parse partition expr failed, sql: {}", serializedObject.expressionSql);
                    continue;
                }
                partitionRefTableExprs.add(partitionExpr);
                
                SlotRef partitionSlotRef = getMvPartitionSlotRef(partitionExpr);
                partitionExprMaps.put(partitionExpr, partitionSlotRef);
            }
        }

        
        if (serializedPartitionExprMaps != null) {
            for (Map.Entry<GsonUtils.ExpressionSerializedObject, GsonUtils.ExpressionSerializedObject> entry :
                    serializedPartitionExprMaps.entrySet()) {
                if (entry.getKey() != null && entry.getValue() != null) {
                    Expr partitionExpr = parsePartitionExpr(entry.getKey().expressionSql, partitionCol);
                    if (partitionExpr == null) {
                        LOG.warn("parse partition expr failed, sql: {}", entry.getKey().expressionSql);
                        continue;
                    }
                    SlotRef partitionSlotRef = getMvPartitionSlotRef(partitionExpr);
                    partitionExprMaps.put(partitionExpr, partitionSlotRef);
                }
            }
        }
    }