【问题标题】:GSON: encode map of objects and preserve type when decodingGSON:编码对象映射并在解码时保留类型
【发布时间】:2019-05-28 11:10:28
【问题描述】:

我有这样的课:

public class MyClass {
    private final Map<Property, Object> properties;
} 

其中Propertyenum
假设属性包含 2 个元素,一个其值为 Double,另一个其值为只有一个名为 ownerName 的属性的类实例。当我序列化这个类时,我得到以下字符串:

{"properties":{"NAME":{"ownerName":"MyBucket"},"DIVISOR":33.0}}

问题是,当我尝试从上面的字符串中获取MyClass 实例时,NAME 属性的值将是Map,而不是具有ownerName 属性的类的实例。我试图编写一个自定义的serializer/deserializer,但我不能只为NAME 属性做到这一点。有什么想法吗?

【问题讨论】:

    标签: java json gson deserialization json-deserialization


    【解决方案1】:

    您需要为整个Map 编写自定义反序列化器。自定义反序列化器可能如下所示:

    class PropertyJsonDeserializer implements JsonDeserializer<Map<Property, Object>>, JsonSerializer<Map<Property, Object>> {
    
        @Override
        public Map<Property, Object> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            if (!json.isJsonObject()) {
                return Collections.emptyMap();
            }
    
            JsonObject root = json.getAsJsonObject();
            Map<Property, Object> result = new LinkedHashMap<>();
            root.entrySet().forEach(entry -> {
                Property property = Property.valueOf(entry.getKey());
                switch (property) {
                    case DIVISOR:
                        result.put(property, entry.getValue().getAsDouble());
                        break;
                    case NAME:
                        Object owner = context.deserialize(entry.getValue(), Owner.class);
                        result.put(property, owner);
                }
            });
            return result;
        }
    
        @Override
        public JsonElement serialize(Map<Property, Object> src, Type typeOfSrc, JsonSerializationContext context) {
            return context.serialize(src, Map.class);
        }
    }
    

    示例用法:

    import com.google.gson.Gson;
    import com.google.gson.GsonBuilder;
    import com.google.gson.JsonDeserializationContext;
    import com.google.gson.JsonDeserializer;
    import com.google.gson.JsonElement;
    import com.google.gson.JsonObject;
    import com.google.gson.JsonParseException;
    import com.google.gson.JsonSerializationContext;
    import com.google.gson.JsonSerializer;
    import com.google.gson.annotations.JsonAdapter;
    
    import java.lang.reflect.Type;
    import java.math.BigDecimal;
    import java.util.Collections;
    import java.util.EnumMap;
    import java.util.LinkedHashMap;
    import java.util.Map;
    
    public class GsonApp {
    
        public static void main(String[] args) throws Exception {
            Map<Property, Object> properties = new EnumMap<>(Property.class);
            properties.put(Property.DIVISOR, new BigDecimal("33.0"));
            properties.put(Property.NAME, new Owner());
    
            MyClass myClass = new MyClass(properties);
    
            Gson gson = new GsonBuilder().setPrettyPrinting().create();
            String json = gson.toJson(myClass);
            System.out.println(json);
    
            myClass = gson.fromJson(json, MyClass.class);
            System.out.println(myClass);
        }
    }
    
    class MyClass {
    
        @JsonAdapter(PropertyJsonDeserializer.class)
        private final Map<Property, Object> properties;
    
        public MyClass(Map<Property, Object> properties) {
            this.properties = properties;
        }
    
        // getters, setters, toString
    }
    
    class Owner {
        private String ownerName = "MyBucket";
    
        // getters, setters, toString
    }
    
    enum Property {
        NAME, DIVISOR
    }
    

    上面的代码打印:

    {
      "properties": {
        "NAME": {
          "ownerName": "MyBucket"
        },
        "DIVISOR": 33.0
      }
    }
    
    MyClass{properties={NAME=Owner{ownerName='MyBucket'}, DIVISOR=33.0}}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-11
      相关资源
      最近更新 更多