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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2435527/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 07:37:43  来源:igfitidea点击:

Use class name as root key for JSON Hymanson serialization

javajsonserializationHymanson

提问by DanInDC

Suppose I have a pojo:

假设我有一个 pojo:

import org.codehaus.Hymanson.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));
    }
}

When I serialize using the Hymanson ObjectMapper, I just get

当我使用 Hymanson ObjectMapper 进行序列化时,我得到了

true
{"id":4}

but I want

但我想要

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

I've searched all over, Hymansons documentation is really unorganized and mostly out of date.

我到处搜索,Hymanson 的文档真的很杂乱无章,而且大多已经过时了。

回答by Aito

I'm not using Hymanson, but searching I found this configuration that seems to be what you want: WRAP_ROOT_VALUE

我没有使用 Hymanson,但搜索我发现这个配置似乎是你想要的:WRAP_ROOT_VALUE

Feature that can be enabled to make root value (usually JSON Object but can be any type) wrapped within a single property JSON object, where key as the "root name", as determined by annotation introspector (esp. for JAXB that uses @XmlRootElement.name) or fallback (non-qualified class name). Feature is mostly intended for JAXB compatibility.

Default setting is false, meaning root value is not wrapped.

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

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

So that you can configure mapper:

以便您可以配置映射器:

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

I hope it helps you...

我希望它能帮助你...

回答by StaxMan

How about simplest possible solution; just use a wrapper class like:

最简单的解决方案怎么样?只需使用一个包装类,如:

class Wrapper {
   public MyPojo MyPojo;
}

and wrapping/unwrapping in your code?

并在您的代码中包装/展开?

Beyond this, it would help to know WHY you would like additional json object entry like this? I know this is done by libs that emulate json via xml api (because of impedance between xml and json, due to conversion from xml to json), but for pure json solutions it is usually not needed.

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

Is it to allow you do figure out what actual type is? If so, perhaps you could consider enabled polymorphic type information, to let Hymanson handle it automatically? (see 1.5 release notes, entry for PTH, for details).

是为了让您弄清楚实际类型是什么?如果是这样,也许您可​​以考虑启用多态类型信息,让Hyman逊自动处理它?(有关详细信息,请参阅1.5 发行说明,PTH 条目)。

回答by Tony

I would be interested in hearing the OP's solution for this. I'm having similar issues where my RESTful web service is serializing objects as either XML or JSON for clients. The Javascript clients need to know the wrapping type so that can parse it. Coupling the type to a URI pattern is not an option.

我有兴趣听到 OP 对此的解决方案。我遇到了类似的问题,我的 RESTful Web 服务将对象序列化为 XML 或 JSON 供客户端使用。Javascript 客户端需要知道包装类型以便解析它。将类型耦合到 URI 模式不是一种选择。

Thanks.

谢谢。

Edit: I noticed that Spring MappingHymansonJsonMarshaller adds the wrapping class when marshalling, so I stepped through the code in debug and noticed that Spring passes in a HashMap with a single key-value pair such that the key is the wrapping name and the value is the object. So, I extended HymansonJaxbJsonProvider, override the writeTo() method and added the following:

编辑:我注意到 Spring MappingHymansonJsonMarshaller 在编组时添加了包装类,所以我在调试中逐步完成了代码并注意到 Spring 传入了一个带有单个键值对的 HashMap,这样键是包装名称,值是目的。因此,我扩展了 HymansonJaxbJsonProvider,覆盖了 writeTo() 方法并添加了以下内容:

HashMap<String, Object> map = new HashMap<String, Object>();
map.put(value.getClass().getSimpleName(), value);
super.writeTo(map, type, genericType, annotations, mediaType, httpHeaders,entityStream);

It's a bit of a hack, but it works nicely.

这有点hack,但效果很好。

回答by shailendra

there is another way i used and that worked for me. I am working with a third party jar, so i have no control for annotations. So i had to write through bit of hack.

我使用了另一种方法,它对我有用。我正在使用第三方 jar,所以我无法控制注释。所以我不得不通过一些黑客来写。

Override: org.codehaus.Hymanson.map.ser.BeanSerializerFactory.findBeanProperties(SerializationConfig, BasicBeanDescription)

覆盖: org.codehaus.Hymanson.map.ser.BeanSerializerFactory.findBeanProperties(SerializationConfig, BasicBeanDescription)

Add your property as below

添加您的财产如下

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;

This way i get more control and can do other kind of filters too.

这样我可以获得更多的控制权,也可以做其他类型的过滤器。

回答by Anish George

Below is a way to achieve this

下面是实现这一目标的方法

Map<String, MyPojo> singletonMap = Collections.singletonMap("mypojo", mp);
System.out.println(mapper.writeValueAsString(singletonMap));

Output{ "mypojo" : { "id" : 4}}

输出{ "mypojo" : { "id" : 4}}

Here the advantage is that we can give our on name for the root key of json object. By the above code, mypojowill be the root key. This approach will be most useful when we use java script template like Mustache.js for iteration of json objects

这里的优点是我们可以为 json 对象的根键提供我们的名称。通过上面的代码,mypojo将是根密钥。当我们使用像 Mustache.js 这样的 java 脚本模板来迭代 json 对象时,这种方法将是最有用的

回答by Arun Prakash

By adding the Hymanson annotation @JsonTypeInfoin class level you can have the expected output. i just added no-changes in your class.

通过@JsonTypeInfo在类级别添加 Hymanson 注释,您可以获得预期的输出。我只是在你的班级中添加了无变化。

package com.test.Hymanson;

import org.codehaus.Hymanson.map.ObjectMapper;
import org.codehaus.Hymanson.map.SerializationConfig;

import com.fasterxml.Hymanson.annotation.JsonTypeInfo;
import com.fasterxml.Hymanson.annotation.JsonTypeInfo.As;
import com.fasterxml.Hymanson.annotation.JsonTypeInfo.Id;

@JsonTypeInfo(include=As.WRAPPER_OBJECT, use=Id.NAME)
public class MyPojo {
    // Remain same as you have
}

output:

输出:

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

回答by JeanValjean

There is also a nice annotation for this:

还有一个很好的注释:

@JsonRootName(value = "my_pojo")
public class MyPojo{
  ...
}

will generate:

将产生:

{
  "my_pojo" : {...}
}

回答by Naushad Idrisi

@JsonTypeInfo(include=As.WRAPPER_OBJECT, use=Id.NAME) 

This annotation works perfectly , as suggested by Arun Prakash . I was trying to get json in this form.

正如 Arun Prakash 所建议的那样,此注释非常有效。我试图以这种形式获取 json。

{"Rowset":{"ROW":{"receiptno":"881604199388936","status":"SUCCESS"}}}

but getting like this:

但得到这样的:

{"ROW":{"receiptno":"881604199388936","status":"SUCCESS"}}}

Now that annotation resolved my problem .

现在该注释解决了我的问题。

回答by winry

use withRootName.

与RootName 一起使用。

objectMapper.writer().withRootName(MyPojo.class.getName());

回答by user2083529

To achieve this you need to use the JsonTypeInfoannotation on your class and in particular WRAPPER_OBJECT

为了实现这一点,你需要JsonTypeInfo在你的类上使用注释,特别是WRAPPER_OBJECT

@JsonTypeName("foo")                                                                                         
@JsonTypeInfo(include = JsonTypeInfo.As.WRAPPER_OBJECT ,use = JsonTypeInfo.Id.NAME)

public class Bar(){
)