【问题标题】:json to java hashmap using complex keyjson 到 java hashmap 使用复杂键
【发布时间】:2017-01-04 09:49:21
【问题描述】:

我目前正在开发一个需要序列化 HashMap<Object1, Object2> 转换为 JSON,然后从 JSON 反序列化为相同的 `HashMap'。

我可以使用通常的映射器对其进行序列化,并覆盖Object1toString() 方法。

public String toString(){
    String res = Object1.elem1 + ";" + Object1.elem2;
    return res
}

然后我可以序列化并获得预期的 json(其中 res 是我之前定义的字符串,更容易不写回它)。*

{res : Object2JsonRepresentation}

然后我想反序列化,所以我使用自定义keyDeserializer:

@XmlElement(name="myMap")
@JsonDeserialize(keyUsing = Object1KeyDeserializer.class)
public HashMap <Object1,Object2> myMap  = new HashMap <>();

还有Object1KeyDeserializer

public class Object1KeyDeserializer extends KeyDeserializer{
    @Override
    public Object1 deserializeKey(String key, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        String[] parts = key.split(";");
        System.out.println(key);
        Elem elem1 = new Elem(parts[1]);
        Elem elem2 = new Elem(parts[2]);
        Object1 obj = new Object1(elem1,elem2);
        return obj;
    }
}

尽管如此,keyDeserializer 似乎从未被调用过,你能解释一下原因吗?我对 JSON 很陌生,如果可以详细回答我会很高兴。

【问题讨论】:

  • 添加注释本身通常是不够的。您需要在构建中的某个地方配置一些插件来获取注释并完成工作。请提供有关您如何构建应用程序的更多详细信息。
  • 嗯,它是开发环境中更大应用程序的一部分,构建工作是使用 gradle 完成的。对于 json,我使用 ObjectMapper 和 writeValueAsString。要反序列化我做 mapper.readValue(jsonString, type)
  • @AdriaanKoster 有什么运行时注释应该由 Jackson 在运行时评估以更改构建?注释不仅可以用于在构建时生成内容。
  • 谢谢你的回答,不过我不太明白我们要去哪里。
  • 在构建中,通常会指定存在哪些依赖项以及将哪些插件和处理器应用于项目生命周期。如果 @JsonDeserialize 注释没有按预期被拾取,我将开始查看构建以查看是否缺少任何内容。

标签: java json hashmap key deserialization


【解决方案1】:

您可以创建自己的序列化格式,而不是使用 toString()。如果您在 Map 中有非原始键,则可以将 Map 序列化为

[
    {
        "key": <serialized key>,
        "value: <serialized value>
    },
    ....
]

在这种情况下,您的序列化器和反序列化器将如下:

public class CustomSerializer extends StdSerializer<Map<Object1, Object2>> {

    protected CustomSerializer() {
        super(Map.class, true);
    }

    @Override
    public void serialize(Map<Object1, Object2> map,
                          JsonGenerator jsonGenerator,
                          SerializerProvider serializerProvider) throws IOException{

        jsonGenerator.writeStartArray();
        for (Map.Entry<Object1,Object2> element: map.entrySet()) {
            jsonGenerator.writeStartObject();
            jsonGenerator.writeObjectField("key", element.getKey());
            jsonGenerator.writeObjectField("value", element.getValue());
            jsonGenerator.writeEndObject();
        }
        jsonGenerator.writeEndArray();
    }
}

public class CustomDeserializer extends StdDeserializer<Map<Object1, Object2>> {
    protected CustomDeserializer() {
        super(Map.class);
    }

    @Override
    public Map<Object1, Object2> deserialize(JsonParser jsonParser,
                                             DeserializationContext deserializationContext) throws IOException {
        Map<Object1, Object2> result = new HashMap<>();
        JsonNode node = jsonParser.getCodec().readTree(jsonParser);
        for (JsonNode element : node) {
            result.put(
                    jsonParser.getCodec().treeToValue(element.get("key"), Object1.class),
                    jsonParser.getCodec().treeToValue(element.get("value"), Object2.class)
            );
        }
        return result;
    }
}

因此您可以使用您的字段和另一个 Map 创建类(用于检查具有不同类型的地图是否正常工作):

public class MapWrapper {

    @JsonSerialize(using = CustomSerializer.class)
    @JsonDeserialize(using = CustomDeserializer.class)
    private Map<Object1, Object2> map = new HashMap<>();

    private Map<String, String> someMap = new HashMap<>();

    // default constructor, getters, setters
}

序列化值可以如下:

{
  "map": [
    {
      "key": {
        "elem1": "qqq",
        "elem2": "rrr"
      },
      "value": {
        "fieldFromValue": "xxx"
      }
    },
    {
      "key": {
        "elem1": "qqq_two",
        "elem2": "rrr_two"
      },
      "value": {
        "fieldFromValue": "yyy"
      }
    }
  ],
  "someMap": {
    "key1": "value1"
  }
}

【讨论】:

  • 感谢您的详细解答。尽管如此,它仍然使用 toString(),而不是序列化。注释中一定有一些东西没有被解释,但我不知道为什么。
  • 我的错,我只是忘记使用序列化程序初始化 simpleModule,因此,您的解决方案完美运行!谢谢!
  • 我可以使用这种机制解决我的问题。非常感谢。
猜你喜欢
  • 2021-10-27
  • 1970-01-01
  • 1970-01-01
  • 2016-10-02
  • 1970-01-01
  • 1970-01-01
  • 2021-10-15
  • 1970-01-01
  • 2019-10-03
相关资源
最近更新 更多