简体   繁体   English

Java对象序列化并转换为JSON

[英]Java object serialization and conversion to JSON

I have a Java object. 我有一个Java对象。 It has numerous fields that have references to other different kinds of Java objects and sometimes, to itself. 它具有众多字段,这些字段引用了其他不同种类的Java对象有时还引用了其自身。 This object can be best described as a map (or graph) with bi-directional references (or cycles). 最好将此对象描述为具有双向参考(或循环)的地图(或图形)。 I am not authorized to analyze its structure, but in order to solve a problem, I have to serialize this graph and store it in a JSON String. 我无权分析其结构,但为了解决问题,我必须对该图进行序列化并将其存储在JSON字符串中。

The fact that I can't really have a look at the structure of the object, using library classes is my only option (as far as I think). 我实际上不能真正使用对象类来查看对象的结构,这是我唯一的选择(就我而言)。 I have tried json-io, json-lib, google genson, gson and flexjson. 我尝试了json-io,json-lib,google genson,gson和flexjson。 But all of these libraries either get stuck and throw an exception due to the presence of a cycle or are able to return a json (only json-io does this) but with a lot of important fields skipped(the ones that are lazy-loaded, and need getters). 但是所有这些库要么由于存在循环而陷入困境并抛出异常,要么能够返回json(只有json-io会这样做),但是跳过了许多重要的字段(被延迟加载的字段) ,并且需要吸气剂)。

Question: Is there something that exists that I might be missing while testing the above listed libraries just to address my problem? 问题:在测试上面列出的库时,是否仅存在某种我想解决的问题?

The Java object I have is really convoluted but I don't expect it to be as convoluted as objects that might be used by big websites like facebook. 我拥有的Java对象确实很复杂,但是我不希望它像Facebook之类的大型网站所使用的对象那样复杂。 What are some key libraries and their specific configuration that can be used to address my problem? 有哪些密钥库及其特定配置可用于解决我的问题?

I think the best option for you is Jackson Streaming API . 我认为最适合您的选择是Jackson Streaming API It allows you to serailaze a POJO into json while teraversing the Object graph, thus maintaining control over the serailization process and you can detect and handle circular references and any other special cases. 它允许您在对对象图进行划分时将POJO序列化为json,从而保持对序列化过程的控制,并且可以检测和处理循环引用以及任何其他特殊情况。

EDIT: I tried to implement an example that handles circular references but i could not complete it. 编辑:我试图实现一个示例处理循环引用,但我无法完成它。 Here are my intermediate findings: 这是我的中间发现:

  1. Calling the default ObjectMapper.WriteValue(...) results in the following Exception com.fasterxml.jackson.databind.JsonMappingException: Direct self-reference leading to cycle which means Jackson can detect cases of self referencing. 调用默认的ObjectMapper.WriteValue(...)导致以下异常com.fasterxml.jackson.databind.JsonMappingException: Direct self-reference leading to cycle ,这意味着Jackson可以检测到自引用的情况。 The default derializer does not know how to handle this case. 默认的derializer不知道如何处理这种情况。
  2. The default behavior of throwing exception can be turned off by specifying mapper.configure(SerializationFeature.FAIL_ON_SELF_REFERENCES, false); 可以通过指定mapper.configure(SerializationFeature.FAIL_ON_SELF_REFERENCES, false);来关闭抛出异常的默认行为mapper.configure(SerializationFeature.FAIL_ON_SELF_REFERENCES, false); when this is set, The default derializer will cause stack overflow. 设置此选项后,默认的序列化器将导致堆栈溢出。 so we need to implement a custom serializer which detects and handles the self referencing. 因此,我们需要实现一个自定义的序列化程序,该序列化程序可以检测并处理自引用。
  3. I tried to write a custom serializer that does the following: a) detect self referencing. 我试图编写一个执行以下操作的自定义序列化程序:a)检测自引用。 b) if found, print something to mark the reference. b)如果找到,请打印一些内容以标记参考。 c) if not, do the default serialization. c)如果不是,请执行默认序列化。 However, I could not see how to call "default serialization". 但是,我看不到如何调用“默认序列化”。 My intermediate solution is listed below: 我的中间解决方案如下:

An example class that can have self reference: 可以具有自我引用的示例类:

public class Node {
    public String name = "";
    public Node child = null;

    public Node(String name) { this.name = name; }

    public String getname()        { return name; }
    public Node   getChild()       { return child; }
    public void   setChild(Node n) { child = n; }
}

the custom serializer 自定义序列化器

public class NodeJsonSerializer extends JsonSerializer<Node> {
    // list so we can detect multiple cases of self references
    static List<Node> alreadySerializedNodes = new ArrayList<>();

    @Override
    public void serialize(Node n, JsonGenerator gen, SerializerProvider serializers) 
            throws IOException, JsonProcessingException {
        for (Node alreadySerialized : alreadySerializedNodes) {
            // do not invoke equals() since you want to find duplicate references 
            if (alreadySerialized == n) {
                // mark this as self reference 
                gen.writeStartObject();
                gen.writeStringField("node-ref", alreadySerialized.getname());
                gen.writeEndObject();
                return;
            }
        }
        alreadySerializedNodes.add(n);

        // default derialization ...
        gen.writeStartObject();
        gen.writeStringField("name", n.getname());
        gen.writeObjectField("child", n.getChild());
        gen.writeEndObject();
    }
}

Calling: 致电:

Node n1 = new Node("n1");
n1.setChild(n1);  // self referencing

ObjectMapper mapper = new ObjectMapper();
// registering custom serializer is through module 
SimpleModule sm = new SimpleModule("MyModule");
sm.addSerializer(Node.class, new NodeJsonSerializer());
// making sure default serializer ignores self referencing is through module mapper.configure(SerializationFeature.FAIL_ON_SELF_REFERENCES, false);
mapper.registerModule(sm);

System.out.println(mapper.writeValueAsString(n1));

output is {"name":"n1","child":{"node-ref":"n1"}} 输出为{"name":"n1","child":{"node-ref":"n1"}}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM