简体   繁体   English

杰克逊序列化:包裹领域

[英]Jackson serialization: Wrap fields

There is a good known case when we unwrap nested object and write its fields into the main object, and I need to make an inverse task. 当我们打开嵌套对象并将其字段写入主对象时,有一个众所周知的情况,我需要做一个反向任务。

I have a POJO: 我有一个POJO:

class A {
    private String id = "id1";

    @JsonWrap("properties")
    private String property1 = "...";

    @JsonWrap("properties")
    private String property2 = "...";

    // getters and setters
}

Default serializer will produce as expected 默认序列化程序将按预期生成

{
    "id": "id1",
    "property1": "...",    
    "property2": "..."    
}

But, my JSON should match some specification, and to do that, I need to wrap property1 and property2 inside properties wrapper. 但是,我的JSON应该符合某些规范,为此,我需要将property1property2包装在properties包装器中。 So the result should looks like: 所以结果应该是这样的:

{
    "id": "id1",
    "properties": 
    {
        "property1": "...",
        "property2": "..."
    }
}

I don't want to change the structure of the POJO so I see 3 possible ways: 我不想改变POJO的结构,所以我看到了3种可能的方法:

  1. Write custom serializer. 编写自定义序列化器。 But as it seems to me, to write such serializer will takes more efforts then serialize objects by hands. 但在我看来,编写这样的序列化器将需要更多的努力,然后手动序列化对象。
  2. Create proxy Java object which will reflect the right structure of JSON, and serialize such proxy. 创建代理Java对象,它将反映JSON的正确结构,并序列化此类代理。
  3. Modify JSON after it have been generated. 生成后修改JSON。 (I'm afraid it would be a great overhead for rereading and rewriting of JSON). (我担心重读和重写JSON会有很大的开销)。

Does anybody make such Serializer or maybe know another options to generate JSON with the structure I need? 有没有人制作这样的Serializer或者可能知道用我需要的结构生成JSON的其他选项?

For custom serializer I want to reuse standard BeanSerializer, I dont want to write out all fields manually: 对于custom serializer我想重用标准BeanSerializer,我不想手动写出所有字段:

  1. Hide annotated fields. 隐藏带注释的字段。
  2. Write out bean, without annotated fields, but don't close object. 写出bean,没有带注释的字段,但不要关闭对象。 (Don't call jgen.writeEndObject(); ) (不要调用jgen.writeEndObject();
  3. Write out wrapped fields. 写出包装的字段。
  4. Close object. 关闭对象。

You need change your model. 你需要改变你的模型。

@JsonSerialize(using = ASerializer.class)
class A {
    private String id;
    private String property1;
    private String property2;

    // getters and setters

    public static class ASerializer extends JsonSerializer<A> {
        @Override
        public void serialize(A value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
            jgen.writeStartObject();
            jgen.writeStringField("id", value.getId());
            jgen.writeObjectFieldStart("properties");
            jgen.writeStringField("property1", value.getProperty1());
            jgen.writeStringField("property2", value.getProperty2());
            jgen.writeEndObject();
            jgen.writeEndObject();
        }
    }
}

Run in main: 在主要运行:

A a = new A();
a.setId("id1");
a.setProperty1("...");
a.setProperty2("...");
ObjectMapper mapper = new ObjectMapper();
ObjectWriter writer = mapper.writer();
String json = writer.writeValueAsString(a);
System.out.println(json);

output: 输出:

{"id":"id1","properties":{"property1":"...","property2":"..."}}

It sounds like you need to create a Custom Serializer: http://wiki.fasterxml.com/JacksonHowToCustomSerializers 听起来你需要创建一个Custom Serializer: http//wiki.fasterxml.com/JacksonHowToCustomSerializers

Of course, if you are creating Java objects from a similar JSON structure you'll likely need to create a Custom Deserializer as well. 当然,如果您从类似的JSON结构创建Java对象,您可能还需要创建自定义反序列化器。

Remember, you can always use reflection to create a 'generic' serializer if you find many of your objects share a similar structure. 请记住,如果您发现许多对象共享相似的结构,则始终可以使用反射来创建“通用”序列化程序。

To get that functionality without altering your model, take a look at writing a custom serializer to accomplish what Jackson can't figure out natively. 要在不改变模型的情况下获得该功能,请查看编写自定义序列化程序以完成杰克逊无法理解的内容。 We annotate the model class A with specific directions to use a defined serializer, and then use the JsonGenerator to specifically define the structure we are after. 我们使用特定的方向注释模型类A以使用已定义的序列化程序,然后使用JsonGenerator专门定义我们之后的结构。

@JsonSerialize(using = ASerializer.class)
class A {
    private String field1;
    private String innerField1;
    private String innerField2;
    // getters and setters


    public static class ASerializer extends JsonSerializer<A> {
        @Override
        public void serialize(A value, JsonGenerator jgen, SerializerProvider provider) 
          throws IOException, JsonProcessingException {
            jgen.writeStartObject();
                jgen.writeStringField("field1", value.getField1());
                jgen.writeObjectFieldStart("wrapper");
                    jgen.writeStringField("innerField1", value.getInnerField1());
                    jgen.writeStringField("innerField2", value.getInnerField2());
                jgen.writeEndObject();
            jgen.writeEndObject();
        }
    }
}

I used a static inner class in this case, but feasibly you can place the Serializer wherever best fits your project structure based on visibility. 在这种情况下,我使用了静态内部类,但可行的是,您可以根据可见性将Serializer放置在最适合您的项目结构的位置。 For one-off special case serializers, this is what I tend to do. 对于一次性特殊情况序列化器,这是我倾向于做的。

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

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