Java 使用类名作为JSON序列化的根键

Java 使用类名作为JSON序列化的根键,java,json,serialization,jackson,Java,Json,Serialization,Jackson,假设我有一个pojo: import org.codehaus.jackson.map.*; public class MyPojo { int id; public int getId() { return this.id; } public void setId(int id) { this.id = id; } public static void main(String[] args) throws Exception {

假设我有一个pojo:

import org.codehaus.jackson.map.*;

public class MyPojo {
    int id;
    public int getId()
    { return this.id; }

    public void setId(int id)
    { this.id = id; }

    public static void main(String[] args) throws Exception {
        MyPojo mp = new MyPojo();
        mp.setId(4);
        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(SerializationConfig.Feature.WRAP_ROOT_VALUE, true);
        System.out.println(mapper.getSerializationConfig().isEnabled(SerializationConfig.Feature.WRAP_ROOT_VALUE));
        System.out.println(mapper.writeValueAsString(mp));
    }
}
当我使用Jackson ObjectMapper序列化时,我只得到

true
{"id":4}
但是我想要

true
{"MyPojo":{"id":4}}

我搜索了所有地方,Jacksons的文档非常杂乱无章,大部分都过时了

我没有使用jackson,但我在搜索中找到了这个配置,它似乎正是您想要的:

可以使根值(通常是JSON对象,但可以是任何类型)包装在单个属性JSON对象中的功能,其中键作为“根名称”,由注释内省器(特别是使用@XmlRootElement.name的JAXB)或回退(非限定类名)确定。该特性主要用于JAXB兼容性

默认设置为false,表示根 值未包装

以便您可以配置映射器:

objectMapper.configure(SerializationConfig.Feature.WRAP_ROOT_VALUE, true);

我希望它能帮助您……

我没有使用jackson,但在搜索中我找到了您想要的配置:

可以使根值(通常是JSON对象,但可以是任何类型)包装在单个属性JSON对象中的功能,其中键作为“根名称”,由注释内省器(特别是使用@XmlRootElement.name的JAXB)或回退(非限定类名)确定。该特性主要用于JAXB兼容性

默认设置为false,表示根 值未包装

以便您可以配置映射器:

objectMapper.configure(SerializationConfig.Feature.WRAP_ROOT_VALUE, true);

我希望它能帮助你……

最简单的解决方案如何;只需使用如下包装器类:

class Wrapper {
   public MyPojo MyPojo;
}
以及在代码中包装/展开

除此之外,了解您为什么需要这样的附加json对象条目也会有所帮助?我知道这是由libs完成的,libs通过xmlapi模拟json(由于xml和json之间的阻抗,由于从xml到json的转换),但对于纯json解决方案,通常不需要它

这是为了让你弄清楚实际的类型是什么吗?
如果是这样,也许你可以考虑启用多态的类型信息,让杰克逊自动处理它?(详见PTH条目)。

最简单的解决方案如何;只需使用如下包装器类:

class Wrapper {
   public MyPojo MyPojo;
}
以及在代码中包装/展开

除此之外,了解您为什么需要这样的附加json对象条目也会有所帮助?我知道这是由libs完成的,libs通过xmlapi模拟json(由于xml和json之间的阻抗,由于从xml到json的转换),但对于纯json解决方案,通常不需要它

这是为了让你弄清楚实际的类型是什么吗?
如果是这样,也许你可以考虑启用多态的类型信息,让杰克逊自动处理它?(有关详细信息,请参阅PTH条目)。

我很想听听OP对此的解决方案。我遇到了类似的问题,我的RESTfulWeb服务将对象序列化为XML或JSON,用于客户端。Javascript客户端需要知道包装类型,以便能够解析它。将类型耦合到URI模式不是一个选项

谢谢

编辑:我注意到Spring MappingJacksonJsonMarshaller在编组时添加了包装类,因此我在调试中仔细检查了代码,并注意到Spring在HashMap中传递了一个键-值对,这样键就是包装名称,值就是对象。因此,我扩展了JacksonJaxbJsonProvider,重写writeTo()方法,并添加了以下内容:

HashMap<String, Object> map = new HashMap<String, Object>();
map.put(value.getClass().getSimpleName(), value);
super.writeTo(map, type, genericType, annotations, mediaType, httpHeaders,entityStream);
HashMap map=newhashmap();
put(value.getClass().getSimpleName(),value);
super.writeTo(映射、类型、genericType、注释、mediaType、HttpHeader、entityStream);

这有点像黑客,但效果很好。

我很想听听OP的解决方案。我遇到了类似的问题,我的RESTfulWeb服务将对象序列化为XML或JSON,用于客户端。Javascript客户端需要知道包装类型,以便能够解析它。将类型耦合到URI模式不是一个选项

谢谢

编辑:我注意到Spring MappingJacksonJsonMarshaller在编组时添加了包装类,因此我在调试中仔细检查了代码,并注意到Spring在HashMap中传递了一个键-值对,这样键就是包装名称,值就是对象。因此,我扩展了JacksonJaxbJsonProvider,重写writeTo()方法,并添加了以下内容:

HashMap<String, Object> map = new HashMap<String, Object>();
map.put(value.getClass().getSimpleName(), value);
super.writeTo(map, type, genericType, annotations, mediaType, httpHeaders,entityStream);
HashMap map=newhashmap();
put(value.getClass().getSimpleName(),value);
super.writeTo(映射、类型、genericType、注释、mediaType、HttpHeader、entityStream);

这有点像黑客,但效果很好。

我使用了另一种方法,这对我很有用。 我使用的是第三方jar,因此无法控制注释。 所以我不得不通过一些黑客手段来写作

重写:
org.codehaus.jackson.map.ser.BeanSerializerFactory.findBeanProperties(SerializationConfig,BasicBeanDescription)

添加您的属性,如下所示

List<BeanPropertyWriter> props = super.findBeanProperties(config, beanDesc);
BeanPropertyWriter bpw = null;
try {
     Class cc = beanDesc.getType().getRawClass();
     Method m = cc.getMethod("getClass", null);
     bpw = new BeanPropertyWriter("$className", null, null, m, null,true, null);
} catch (SecurityException e) {
  // TODO
} catch (NoSuchMethodException e) {
  // TODO
}
props.add(bpw);
return props;
List props=super.findBeanProperties(config,beanDesc);
BeanPropertyWriter bpw=null;
试一试{
类cc=beanDesc.getType().getRawClass();
方法m=cc.getMethod(“getClass”,null);
bpw=新BeanPropertyWriter($className),null,null,m,null,true,null);
}捕获(安全异常e){
//待办事项
}捕获(无此方法例外){
//待办事项
}
道具添加(bpw);
返回道具;

通过这种方式,我可以获得更多的控制权,也可以使用其他类型的过滤器。

我还使用了另一种方式,这种方式对我很有效。 我使用的是第三方jar,因此无法控制注释。 所以我不得不通过一些黑客手段来写作

重写:
org.codehaus.jackson.map.ser.BeanSerializerFactory.findBeanProperties(SerializationConfig,BasicBeanDescription)

添加您的属性,如下所示

List<BeanPropertyWriter> props = super.findBeanProperties(config, beanDesc);
BeanPropertyWriter bpw = null;
try {
     Class cc = beanDesc.getType().getRawClass();
     Method m = cc.getMethod("getClass", null);
     bpw = new BeanPropertyWriter("$className", null, null, m, null,true, null);
} catch (SecurityException e) {
  // TODO
} catch (NoSuchMethodException e) {
  // TODO
}
props.add(bpw);
return props;
List props=super.findBeanProperties(config,beanDesc);
BeanPropertyWriter bpw=null;
试一试{
类cc=beanDesc.getType().getRawClass();
方法m=cc.getMethod(“getClass”,null);
bpw=新
{
  "my_pojo" : {...}
}
@JsonTypeInfo(include=As.WRAPPER_OBJECT, use=Id.NAME) 
{"Rowset":{"ROW":{"receiptno":"881604199388936","status":"SUCCESS"}}}
{"ROW":{"receiptno":"881604199388936","status":"SUCCESS"}}
objectMapper.writer().withRootName(MyPojo.class.getName());
@JsonTypeName("foo")                                                                                         
@JsonTypeInfo(include = JsonTypeInfo.As.WRAPPER_OBJECT ,use = JsonTypeInfo.Id.NAME)

public class Bar(){
)
  <component :is="child.componentType"/>.