使用Jackson进行循环引用的密钥序列化

时间:2013-08-27 21:54:07

标签: serialization map key jackson

我正在尝试将HashMap从Objects序列化为字符串,但是特定的Object具有对当前类的引用,导致无限递归,这似乎不能通过常用的JsonIdentifyInfo注释来解决。这是一个例子:

public class CircularKey {

    public void start() throws IOException {
        ObjectMapper mapper = new ObjectMapper();

        Cat cat = new Cat();

        // Encode
        String json = mapper.writeValueAsString(cat);
        System.out.println(json);

        // Decode
        Cat cat2 = mapper.readValue(json, Cat.class);
        System.out.println(mapper.writeValueAsString(cat2));
    }
}

@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "@id")
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
class Mouse {
    int id;

    @JsonProperty
    Cat cat;
}

@JsonIdentityInfo(generator = ObjectIdGenerators.IntSequenceGenerator.class, property = "@id")
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
class Cat {
    int id;

    @JsonSerialize(keyUsing = MouseMapKeySerializer.class)
    @JsonDeserialize(keyUsing = MouseMapKeyDeserializer.class)
    @JsonProperty
    HashMap<Mouse, String> status = new HashMap<Mouse, String>();

    public Cat() {
        Mouse m = new Mouse();
        m.cat = this;
        status.put(m, "mike");
    }

}

这是密钥的序列化器/解串器:

class MouseMapKeySerializer extends JsonSerializer<Mouse> {
static ObjectMapper mapper = new ObjectMapper();

@Override
public void serialize(Mouse value, JsonGenerator generator,
        SerializerProvider provider) throws IOException,
        JsonProcessingException {
    String json = mapper.writeValueAsString(value);
    generator.writeFieldName(json);
}
}

class MouseMapKeyDeserializer extends KeyDeserializer {
static ObjectMapper mapper = new ObjectMapper();

@Override
public Mouse deserializeKey(String c, DeserializationContext ctx)
        throws IOException, JsonProcessingException {
    return mapper.readValue(c, Mouse.class);
}
}

如果我将地图切换到HashMap(字符串,对象),它可以工作,但我无法更改原始映射。有什么想法吗?

1 个答案:

答案 0 :(得分:0)

您似乎在http://jackson-users.ning.com/forum/topics/serializing-hashmap-with-object-key-and-recursion找到了答案。这似乎不可能,因为:

  

复杂的键是棘手的,它不是我曾经考虑过的用例。然而,没有什么特别阻止使用标准组件;主要关注的只是JSON所具有的限制(必须是String-value,JsonParser / JsonGenerator将键暴露为不同的标记)。   对于Object键,没有明确支持多态类型或对象ID。标准串行器/解串器主要用于相对简单的类型,可以轻松可靠地转换为字符串;数字,日期,UUID。

     

所以:与价值处理程序不同,模块化设计(分离TypeSerializer / JsonSerializer)是有道理的,我认为你需要做的是拥有处理所有方面的自定义(de)序列化程序。您应该能够使用现有值(de)序列化程序中的代码,键入(de)序列化程序,但不能使用类本身。

     

你的用例确实听起来很有趣,但无论好坏,它都在推动信封的发展。 : - )