在Spring Data Rest中使用自定义json序列化程序时输出不同的JSON [英] Different JSON output when using custom json serializer in Spring Data Rest

查看:385
本文介绍了在Spring Data Rest中使用自定义json序列化程序时输出不同的JSON的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据 Jackson 序列化程序后。 x / reference / html / representationations-chapter.html#d5e394rel =nofollow noreferrer>官方文档我观察到一种略有不同的json输出格式。

After adding a custom Jackson serializer based on the official documenation I've observed a slightly different json output format.

此示例基于 spring-restbucks 的分支。

RepositoryRestMvcConfiguration 扩展 org.springsource.restbucks.WebConfiguration 并覆盖 configureJacksonObjectMapper

@Override
protected void configureJacksonObjectMapper(ObjectMapper objectMapper) {
    final SimpleSerializers serializers = new SimpleSerializers();
    serializers.addSerializer(Order.class, new OrderSerializer());
    objectMapper.registerModule(new SimpleModule("CustomSerializerModule"){
        @Override public void setupModule(SetupContext context) {
            context.addSerializers(serializers);
        }
    });
}

创建类 org.springsource.restbucks.order。 OrderSerializer 。为了简洁起见,只需将属性付费写为JSON。

Create class org.springsource.restbucks.order.OrderSerializer. For the sake of brevity just write attribute paid as JSON.

public class OrderSerializer extends JsonSerializer<Order> {
    @Override
    public void serialize(Order value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
        jgen.writeStartObject();
        jgen.writeBooleanField("paid", value.isPaid());
        jgen.writeEndObject();
    }
}

在为 http:// localhost:8080 / orders / 1 看起来像:

{
  "location": "TAKE_AWAY",
  "status": "PAYMENT_EXPECTED",
  "orderedDate": "2014-03-24T15:05:09.988+01:00",
  "items": [
    {
      "name": "Java Chip",
      "quantity": 1,
      "milk": "SEMI",
      "size": "LARGE",
      "price": {
        "currency": "EUR",
        "value": 4.2
      }
    }
  ],
  "_links": {
    ...
  }
}

添加OrderSerializer json响应后,http:// localhost:8080 / orders / 1 看起来像

{
  "content": {
    "paid": false
  },
  "_links": {
    ...
  }
}

主要的pi npoint是被支付的属性被包装到另一个对象内容中,该内容是 org.springframework.hateoas.Resource 。我期待没有这个属性的回复:

The main pinpoint is that attribute paid is wrapped into another object content which is an attribute of org.springframework.hateoas.Resource. I've expected a response without this attribute:

{
  "paid": false,  
  "_links": {
    ...
  }
}

我查看了杰克逊代码,发现 UnwrappingBeanSerializer 可能是我正在寻找的解决方案。
在查看如何初始化UnwrappingBeanSerializer之后,我认为这个序列化程序并不是为了自定义使用而进行子类化。

I've looked into Jackson code and found that UnwrappingBeanSerializer might be the solution I'm looking for. After looking at how to initialize UnwrappingBeanSerializer I think that this serializer is not meant to be subclassed for custom use.

我想知道使用自定义序列化程序时这种偏离的json格式是正常行为还是Spring Data Rest中的错误。任何形式的帮助都表示赞赏。

I would like to know whether this deviating json format when using a custom serializer is a normal behaviour or a bug in Spring Data Rest. Any kind of help is appreciated.

推荐答案

这不是Spring Data Rest的错误它实际上是Jackson的正常行为串行。每当您使用@JsonUnwrapped Annotation(与资源内容字段一起使用)和自定义序列化程序时,Jackson Serializer将显式写入字段名称(在本例中为内容)。有关更多详细信息,请查看UnwrappingBeanPropertyWriter。无论如何,你使用UnwrappingBeanSerializer一直在正确的轨道上,但设置与通常的Serializer注册略有不同。以下示例应解决您的问题:

This is not a bug of Spring Data Rest it is actually the normal behaviour of the Jackson Serializer. Whenever you use the @JsonUnwrapped Annotation (as the Resource content field does) together with a custom Serializer the Jackson Serializer will explicitly write the field name (in this case content). Have a look at the UnwrappingBeanPropertyWriter for more details. Anyhow you have been on the right track using the UnwrappingBeanSerializer but the setup is slightly different then the usual Serializer registration. The following example should fix your problem:

@Override
protected void configureJacksonObjectMapper(ObjectMapper objectMapper) {
    mapper.registerModule(new Module() {
        @Override
        public String getModuleName() {
            return "my.module";
        }

        @Override
        public Version version() {
            return Version.unknownVersion();
        }

        @Override
        public void setupModule(SetupContext context) {

            context.addBeanSerializerModifier(new BeanSerializerModifier() {
                @Override
                public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> serializer) {
                    if(beanDesc.getBeanClass().equals(Order.class)) {
                        return new UnwrappingOrderSerializer((BeanSerializerBase) serializer, NameTransformer.NOP);
                    }
                    return serializer;
                }
            });
        }
    });
}

public class UnwrappingOrderSerializer extends UnwrappingBeanSerializer {
    public UnwrappingBarSerializer(BeanSerializerBase src, NameTransformer transformer) {
        super(src, transformer);
    }

    @Override
    public JsonSerializer<Object> unwrappingSerializer(NameTransformer transformer) {
        return new UnwrappingOrderSerializer(this, transformer);
    }

    @Override
    protected void serializeFields(Object bean, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonGenerationException {
        Order order = (Order) bean;
        jgen.writeStringField("paid", order.isPaid();
    }

    @Override
    public boolean isUnwrappingSerializer() {
        return true;
    }
}

这篇关于在Spring Data Rest中使用自定义json序列化程序时输出不同的JSON的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆