Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Jackson将Java对象序列化为JSON时抑制包装器对象_Java_Json_Spring_Jackson - Fatal编程技术网

使用Jackson将Java对象序列化为JSON时抑制包装器对象

使用Jackson将Java对象序列化为JSON时抑制包装器对象,java,json,spring,jackson,Java,Json,Spring,Jackson,我有一个以JSON形式返回列表的web服务。它使用Jackson将Java POJO列表映射为JSON。问题是JSON表示在数组周围有一个包装器对象,我只想要数组。也就是说,我得到了这个: {"optionDtoList":[{...}, ..., {...}]} 我真正想要的是: [{...}, ..., {...}] 我直接序列化Java列表;我不是用包装器对象包装列表,也不是序列化包装器对象。Jackson似乎正在添加JavaScript包装器对象 我假设我可以在POJO上使用一些注释

我有一个以JSON形式返回列表的web服务。它使用Jackson将Java POJO列表映射为JSON。问题是JSON表示在数组周围有一个包装器对象,我只想要数组。也就是说,我得到了这个:

{"optionDtoList":[{...}, ..., {...}]}
我真正想要的是:

[{...}, ..., {...}]
我直接序列化Java列表;我不是用包装器对象包装列表,也不是序列化包装器对象。Jackson似乎正在添加JavaScript包装器对象

我假设我可以在POJO上使用一些注释来抑制包装器对象,但我没有看到它

解决方案的限制

我想在服务端解决这个问题,而不是在客户端剥离包装。客户端是一个jQueryUI小部件(自动完成小部件,并不重要),它需要一个简单的数组,我不想修改小部件本身

我尝试过的

  • 我尝试用Java POJO数组替换Java POJO列表,结果是一样的
  • 我试图
    @JsonTypeInfo(use=Id.NONE)
    认为这可能会抑制包装器,但它没有

老实说,我不会太快尝试解决这个问题,因为使用包装器确实会造成代码更具可扩展性的情况。如果将来扩展它以返回其他对象,那么使用此web服务的客户端很可能不需要更改实现

但是,如果所有客户端都希望使用未命名的数组,那么将来在该数组之外添加更多属性可能会破坏统一接口


尽管如此,每个人都有自己的理由想以某种方式做某事。您正在序列化的对象看起来像什么?是序列化包含数组的对象,还是序列化实际数组本身?如果您的POJO包含一个数组,那么解决方案可能是将该数组从POJO中拉出,并将该数组序列化。

您可以编写自定义序列化程序:

public class UnwrappingSerializer extends JsonSerializer<Object>
{
    @Override
    public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider)
            throws IOException, JsonProcessingException
    {
        JavaType type = TypeFactory.type(value.getClass());
        getBeanSerializer(type, provider).serialize(value, new UnwrappingJsonGenerator(jgen), provider);
    }

    private synchronized JsonSerializer<Object> getBeanSerializer(JavaType type, SerializerProvider provider)
    {
        JsonSerializer<Object> result = cache.get(type);
        if (result == null) {
            BasicBeanDescription beanDesc = provider.getConfig().introspect(type);
            result = BeanSerializerFactory.instance.findBeanSerializer(type, provider.getConfig(), beanDesc);
            cache.put(type, result);
        }
        return result;
    }

    private Map<JavaType, JsonSerializer<Object>> cache = new HashMap<JavaType, JsonSerializer<Object>>();

    private static class UnwrappingJsonGenerator extends JsonGeneratorDelegate
    {
        UnwrappingJsonGenerator(JsonGenerator d)
        {
            super(d);
        }

        @Override
        public void writeEndObject() throws IOException, JsonGenerationException
        {
            if (depth-- >= yieldDepth) {
                super.writeEndObject();
            }
        }

        @Override
        public void writeFieldName(SerializedString name) throws IOException, JsonGenerationException
        {
            if (depth >= yieldDepth) {
                super.writeFieldName(name);
            }
        }

        @Override
        public void writeFieldName(String name) throws IOException, JsonGenerationException
        {
            if (depth >= yieldDepth) {
                super.writeFieldName(name);
            }
        }

        @Override
        public void writeStartObject() throws IOException, JsonGenerationException
        {
            if (++depth >= yieldDepth) {
                super.writeStartObject();
            }
        }

        private int depth;
        private final int yieldDepth = 2;
    }
}
公共类展开序列化程序扩展JsonSerializer
{
@凌驾
公共void序列化(对象值、JsonGenerator jgen、SerializerProvider提供程序)
抛出IOException、JsonProcessingException
{
JavaType=TypeFactory.type(value.getClass());
getBeanSerializer(类型,提供程序).serialize(值,新解包JSONGenerator(jgen),提供程序);
}
专用同步JsonSerializer getBeanSerializer(JavaType类型,SerializerProvider提供程序)
{
JsonSerializer result=cache.get(类型);
如果(结果==null){
BasicBeanDescription beanDesc=provider.getConfig().introspect(类型);
结果=BeanSerializerFactory.instance.findBeanSerializer(类型,provider.getConfig(),beanDesc);
cache.put(类型、结果);
}
返回结果;
}
私有映射缓存=新的HashMap();
私有静态类UnwrappingJsonGenerator扩展了JsonGeneratorDelegate
{
展开JsonGenerator(JsonGenerator d)
{
超级(d);
}
@凌驾
public void writeEndObject()引发IOException,JsonGenerationException
{
如果(深度-->=屈服深度){
super.writeEndObject();
}
}
@凌驾
public void writeFieldName(SerializedString名称)引发IOException、JsonGenerationException
{
如果(深度>=屈服深度){
super.writeFieldName(名称);
}
}
@凌驾
public void writeFieldName(字符串名称)引发IOException,JsonGenerationException
{
如果(深度>=屈服深度){
super.writeFieldName(名称);
}
}
@凌驾
public void writeStartObject()引发IOException,JsonGenerationException
{
如果(++深度>=屈服深度){
super.writeStartObject();
}
}
私有整数深度;
私人最终整容深度=2;
}
}
它将忽略深度低于指定深度(默认为2)的外部对象

然后按如下方式使用:

public class UnwrappingSerializerTest
{
    public static class BaseT1
    {
        public List<String> getTest()
        {
            return test;
        }

        public void setTest(List<String> test)
        {
            this.test = test;
        }

        private List<String> test;
    }

    @JsonSerialize(using = UnwrappingSerializer.class)
    public static class T1 extends BaseT1
    {
    }

    @JsonSerialize(using = UnwrappingSerializer.class)
    public static class T2
    {
        public BaseT1 getT1()
        {
            return t1;
        }

        public void setT1(BaseT1 t1)
        {
            this.t1 = t1;
        }

        private BaseT1 t1;
    }

    @Test
    public void test() throws IOException
    {
        ObjectMapper om = new ObjectMapper();
        T1 t1 = new T1();
        t1.setTest(Arrays.asList("foo", "bar"));
        assertEquals("[\"foo\",\"bar\"]", om.writeValueAsString(t1));

        BaseT1 baseT1 = new BaseT1();
        baseT1.setTest(Arrays.asList("foo", "bar"));
        T2 t2 = new T2();
        t2.setT1(baseT1);
        assertEquals("{\"test\":[\"foo\",\"bar\"]}", om.writeValueAsString(t2));
    }
}
公共类展开序列化测试
{
公共静态类BaseT1
{
公共列表getTest()
{
回归试验;
}
公共无效设置测试(列表测试)
{
这个。测试=测试;
}
私有列表测试;
}
@JsonSerialize(使用=UnwrappingSerializer.class)
公共静态类T1扩展了BaseT1
{
}
@JsonSerialize(使用=UnwrappingSerializer.class)
公共静态类T2
{
公共BaseT1 getT1()
{
返回t1;
}
公共void setT1(BaseT1)
{
这是1.t1=t1;
}
专用基站t1;
}
@试验
public void test()引发IOException
{
ObjectMapper om=新的ObjectMapper();
T1=新的T1();
t1.setTest(Arrays.asList(“foo”,“bar”));
assertEquals(“[\'foo\',\'bar\'”),om.writeValueAsString(t1));
BaseT1 BaseT1=新的BaseT1();
baseT1.setTest(Arrays.asList(“foo”,“bar”));
T2=新的T2();
t2.setT1(baseT1);
assertEquals(“{\'test\':[\'foo\',\'bar\']}”,om.writeValueAsString(t2));
}
}
注:

  • 它只需要一个字段包装器,并将在
    {{field1:{…},field2:{…}
  • 如果使用自定义
    SerializerFactory
    ,则可能需要将其传递给序列化程序
  • 它使用单独的序列化程序缓存,因此这也可能是一个问题

在测试模式下运行时:

org.codehaus.jackson.map.ObjectMapper mapper = new org.codehaus.jackson.map.ObjectMapper();
String json = mapper.writeValueAsString( Arrays.asList("one","two","three","four","five") );
System.out.println(json);
返回:

["one","two","three","four","five"]
你期望的行为是什么

当我通过Spring控制器和
    @RequestMapping(value = "/listnowrapper")
public @ResponseBody String listNoWrapper() throws Exception{       
    ObjectMapper mapper = new ObjectMapper();
    return mapper.writeValueAsString(Arrays.asList("one","two","three","four","five")); 
}