使用 Jackson 对带有循环引用的键进行序列化

标签 serialization map key jackson

我正在尝试将 HashMap 从对象序列化为字符串,但特定对象具有对当前类的引用,导致无限递归,这似乎无法通过通常的 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");
    }

}

这是 key 的序列化器/反序列化器:
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 (String,Object) 它可以工作但我无法更改原始映射。有任何想法吗?

最佳答案

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

Complex keys are tricky, and it is not a use case I ever considered. Then again, there is nothing specifically preventing use of standard components; main concern was just the limitations than JSON has (must be String-value, JsonParser/JsonGenerator expose keys as different tokens). There is no explicit support for either polymorphic types or object ids for Object keys. Standard serializers/deserializers are mostly for relatively simple types that can be easily and reliably converted to/from Strings; numbers, Dates, UUIDs.

So: unlike with value handlers, where modular design (with separation of TypeSerializer/JsonSerializer) makes sense, I think what you need to do is to have custom (de)serializers that handle all aspects. You should be able to use code from existing value (de)serializers, type (de)serializers, but not classes themselves.

Your use case does sound interesting, but for better or worse, it is pushing the envelope quite a bit. :-)

关于使用 Jackson 对带有循环引用的键进行序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18476124/

相关文章:

jquery - 使用动态和静态输入php序列化并插入到mysql表单

java - WeakReference 如何影响这个程序的工作

performance - Clojure 并行映射和无限序列

api - 超过 Youtube Data API 配额

hash - 如果使用重复的哈希键插入dynamo DB,会发生什么?

scala - 使用 json4s 解析 JSON 时引发不可序列化异常

java - 将反序列化的对象与其原始对象合并

events - Tkinter 中的多个键事件绑定(bind) - "Control + E" "Command (apple) + E"等

json - NSCoding 和 Codable 属性 <=> JSON 格式 <=>(读/写)文件

scala - 将列表转换为 map 并在一行中获取项目