首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >序列化和反序列化Map<Object,Object> Jackson

序列化和反序列化Map<Object,Object> Jackson
EN

Stack Overflow用户
提问于 2019-11-26 16:59:45
回答 2查看 1.9K关注 0票数 2

我有以下类,我想用Jackson (2.9.10)来序列化/反序列化JSON,使用它的ID引用对象。

代码语言:javascript
复制
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class Key {

    @JsonProperty("id")
    private String id;
    @JsonProperty("random_field_key")
    private boolean randomFieldKey;

    // Getters and setters
}
代码语言:javascript
复制
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public class Value {

    @JsonProperty("id")
    private String id;
    @JsonProperty("random_field_value")
    private boolean randomFieldValue;

    // Getters and setters
}
代码语言:javascript
复制
@JsonPropertyOrder({"keys", "values", "relationships"})
public class Relationship {
    @JsonProperty("keys")
    private List<Key> keys;
    @JsonProperty("values")
    private List<Value> values;
    @JsonProperty("relationships")
    private Map<Key, Value> relationships;

    // Getters and setters
}
代码语言:javascript
复制
public class Main {
    private static final ObjectMapper mapper = new ObjectMapper();

    public static void main(String[] args) throws IOException {


        Value value = new Value();
        value.setId("valueId");
        value.setRandomFieldValue(true);

        Key key = new Key();
        key.setId("keyId");
        key.setRandomFieldKey(false);

        Map<Key, Value> map = new HashMap<Key, Value>();
        map.put(key, value);

        Relationship relationship = new Relationship();
        relationship.setKeys(Collections.singletonList(key));
        relationship.setValues(Collections.singletonList(value));
        relationship.setRelationships(map);

        String serialisedRelationship = mapper.writeValueAsString(relationship);
        Relationship deserialisedRelationship = mapper.readValue(serialisedRelationship, Relationship.class);

    }
}

预期结果如下:

代码语言:javascript
复制
{
    "keys": [
        {
            "id": "keyId",
            "random_field_key": false
        }
    ],
    "values": [
        {
            "id": "valueId",
            "random_field_value": true
        }
    ],
    "relationships": {
        "keyId": "valueId"
    }
}

相反,我得到了:

代码语言:javascript
复制
{
    "keys": [
        {
            "id": "keyId",
            "random_field_key": false
        }
    ],
    "values": [
        {
            "id": "valueId",
            "random_field_value": true
        }
    ],
    "relationships": {
        "util.teststack.Key@8646db9": "valueId"
    }
}

我添加了一个自定义序列化程序,允许将键序列化为Id (我认为JsonIdentityInfo注释会处理这个问题),并设法获得了预期的结果。

代码语言:javascript
复制
public class KeySerializer extends JsonSerializer<Key> {

    @Override
    public void serialize(Key value,
                          JsonGenerator gen,
                          SerializerProvider serializers)
            throws IOException {

        gen.writeFieldName(value.getId());
    }
}
代码语言:javascript
复制
@JsonPropertyOrder({"keys", "values", "relationships"})
public class Relationship {
    @JsonProperty("keys")
    private List<Key> keys;
    @JsonProperty("values")
    private List<Value> values;
    @JsonSerialize(keyUsing = KeySerializer.class)
    @JsonProperty("relationships")
    private Map<Key, Value> relationships;

    // Getters and setters
}

不过,我似乎无法对JSON进行反序列化,而且我总是得到例外:

代码语言:javascript
复制
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot find a (Map) Key deserializer for type [simple type, class util.teststack.Key]

我认为添加自定义反序列化器也是个好主意,但我很难理解如何引用“外部”(已经实例化)关键实例。我在DeserializerContext中所能做的就是实例化一个新键,而不是引用先前创建的键。

检查DeserializerContext我可以看到我需要的所有实例都在那里,但是我不知道如何引用(并返回它们)。令人惊讶的是,Map值的引用在没有序列化程序/反序列化器的情况下正常工作。

代码语言:javascript
复制
public class KeyDeserializer extends com.fasterxml.jackson.databind.KeyDeserializer {

    @Override
    public Key deserializeKey(
            String key,
            DeserializationContext ctxt) {

        Key newKey = new Key();
        newKey.setId(key);

        return newKey;
    }
}
代码语言:javascript
复制
@JsonPropertyOrder({"keys", "values", "relationships"})
public class Relationship {
    @JsonProperty("keys")
    private List<Key> keys;
    @JsonProperty("values")
    private List<Value> values;
    @JsonSerialize(keyUsing = KeySerializer.class)
    @JsonDeserialize(keyUsing = KeyDeserializer.class)
    @JsonProperty("relationships")
    private Map<Key, Value> relationships;
}

调试器

我实现了公认的答案,设法以这样的方式解决问题:

代码语言:javascript
复制
public class KeyDeSerializer extends com.fasterxml.jackson.databind.KeyDeserializer {

    @Override
    public Key deserializeKey(String key, DeserializationContext ctxt) {
        Relationship obj = (Relationship) ctxt.getParser().getParsingContext().getParent().getCurrentValue();
        return getKey(key, obj);
    }

    private Key getKey(String key, Relationship obj) {
        for (Key ck : obj.getKeys()) {
            if (ck.getId().equals(key)) {
                return ck;
            }
        }
        return null;
    }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-11-27 23:01:18

在对象DeserializationContext中,您可以检索关系对象。

试试像这样的东西

代码语言:javascript
复制
ctxt.getParser().getParsingContext().getParent().getCurrentValue();

从这个对象中可以检索所需的实例。

票数 1
EN

Stack Overflow用户

发布于 2019-11-26 18:36:52

请您尝试在您的Key类中重写toString()方法并返回"id“的值。

代码语言:javascript
复制
public String toString() {
  this.id;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59055918

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档