当前位置: 首页 > 面试题库 >

JSON根据类型反序列化

郎飞龙
2023-03-14
问题内容

可以说我有以下格式的JSON:

{
    "type" : "Foo"
    "data" : {
        "object" : {
            "id" : "1"
            "fizz" : "bizz"
            ...
        },
        "metadata" : {
            ...
        },
        "owner" : {
            "name" : "John"
            ...
        }
    }
}

我试图避免自定义反序列化器,并尝试将上述JSON(称为Wrapper.java)反序列化为Java POJO。“类型”字段指示“对象”反序列化,即。type
= foo表示使用Foo.java反序列化“ object”字段。(如果type =
Bar,则使用Bar.java反序列化对象字段)。元数据/所有者将始终使用相同的反序列化方式,每个方法都使用一个简单的带有Jackson注释的Java类。有没有一种方法可以使用注释来完成此任务?如果没有,如何使用自定义解串器完成?


问题答案:


所有这些都可以通过注释来完成。

使用“ metadata”和“ owner”等通用字段及其获取器/设置器创建一个抽象超类。此类需要使用@JsonTypeInfo进行注释。它应该看起来像:

@JsonTypeInfo(use = Id.CLASS, include = As.PROPERTY, property = "type")

使用该参数,property = “type”您可以指定将类别标识符序列化为JSON文档中的字段类型。

可以使用来指定类标识符的值use。Id.CLASS使用标准的Java类名称。您也可以使用Id.MINIMAL_CLASS缩写Java类名。要使用自己的标识符,请使用Id.NAME。在这种情况下,您需要声明子类型:

@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type")
@JsonSubTypes({
    @JsonSubTypes.Type(value = Foo.class, name = "Foo"),
    @JsonSubTypes.Type(value = Bar.class, name = "Bar")
})

通过扩展抽象超类来实现Foo和Bar类。

Jackson的ObjectMapper将使用JSON文档的其他字段“类型”进行序列化和反序列化。例如 当您将JSON字符串反序列化为超类引用时,它将属于适当的子类:

ObjectMapper om = new ObjectMapper();
AbstractBase x = om.readValue(json, AbstractBase.class);
// x will be instanceof Foo or Bar

完整的代码示例(我使用公共字段作为无需编写getter / setter的快捷方式):

package test;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;

import java.io.IOException;

import com.fasterxml.jackson.annotation.JsonSubTypes;

@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type")
@JsonSubTypes({
    @JsonSubTypes.Type(value = Foo.class, name = "Foo"),
    @JsonSubTypes.Type(value = Bar.class, name = "Bar")
})
public abstract class AbstractBase {

    public MetaData metaData;
    public Owner owner;
    @Override
    public String toString() {
        return "metaData=" + metaData + "; owner=" + owner;
    }

    public static void main(String[] args) throws IOException {

        // Common fields
        Owner owner = new Owner();
        owner.name = "Richard";
        MetaData metaData = new MetaData();
        metaData.data = "Some data";

        // Foo
        Foo foo = new Foo();
        foo.owner = owner;
        foo.metaData = metaData;
        CustomObject customObject = new CustomObject();
        customObject.id = 20l;
        customObject.fizz = "Example";
        Data data = new Data();
        data.object = customObject;
        foo.data = data;
        System.out.println("Foo: " + foo);

        // Bar
        Bar bar = new Bar();
        bar.owner = owner;
        bar.metaData = metaData;
        bar.data = "A String in Bar";

        ObjectMapper om = new ObjectMapper();

        // Test Foo:
        String foojson = om.writeValueAsString(foo);
        System.out.println(foojson);
        AbstractBase fooDeserialised = om.readValue(foojson, AbstractBase.class);
        System.out.println(fooDeserialised);

        // Test Bar:
        String barjson = om.writeValueAsString(bar);
        System.out.println(barjson);
        AbstractBase barDeserialised = om.readValue(barjson, AbstractBase.class);
        System.out.println(barDeserialised);

    }

}

class Foo extends AbstractBase {
    public Data data;
    @Override
    public String toString() {
        return "Foo[" + super.toString() + "; data=" + data + ']';
    }
}

class Bar extends AbstractBase {
    public String data;
    public String toString() {
        return "Bar[" + super.toString() + "; data=" + data + ']';
    }
}


class Data {
    public CustomObject object;
    @Override
    public String toString() {
        return "Data[object=" + object + ']';
    }
}

class CustomObject {
    public long id;
    public String fizz;
    @Override
    public String toString() {
        return "CustomObject[id=" + id + "; fizz=" + fizz + ']';
    }
}

class MetaData {
    public String data;
    @Override
    public String toString() {
        return "MetaData[data=" + data + ']';
    }
}

class Owner {
    public String name;
    @Override
    public String toString() {
        return "Owner[name=" + name + ']';
    }
}

 类似资料:
  • 假设我有以下格式的JSON: 我试图避免自定义反序列化程序,并试图将上述JSON(称为Wrapper.java)反序列化为JavaPOJO。“type”字段指示“object”反序列化,即type=foo表示使用foo.java反序列化“object”字段。(如果type=Bar,则使用Bar.java反序列化对象字段)。Metadata/owner将始终以相同的方式对每个元数据使用简单的带Jac

  • 我正在将RedditAPI中的一些内容反序列化到POJO中。我的目标是尽可能简化代码,因为reddit中实体之间的JSON结构通常是相同的。 例如,反序列化链接对象的JSON如下所示: 我可以反序列化这一点没有问题,但由于reddit注释的不同之处在于其类型为t1,并且在其下方的数据对象中具有不同的结构,因此我希望将相同的类结构重新用于JSON包装,而不必创建多个具有一行或两行差异的复制类。 我创

  • 问题内容: 我有一个包含许多元素的XML文档,每个元素都有一个或属性。看到这个例子: 我需要一种方法告诉Simple将元素反序列化为a 和将元素反序列化为a 。 我怎样才能做到这一点? 如果您想使用它,这是我目前拥有的代码: 问题答案: 现在真正的问题… 我的回答: 没有!或至少,没关系! 像这里这样的属性只是字符串,不能做出任何决定。但是还有另一种好方法: 实施要为其做出决定的转换器 使用a 做

  • 问题内容: 我想基于字段值将json对象反序列化为特定类型的对象(使用Gson库),例如: 因此,字段将具有不同(但已知)的值。基于该值,我需要将该json对象反序列化为适当的模型对象,例如:Type1Model,Type2Model等。我知道我可以轻松地在反序列化之前通过将其转换为,迭代并确定应该反序列化为哪种类型来完成此操作。 。但是我认为这是丑陋的方法,我正在寻找更好的方法。有什么建议? 问

  • 问题内容: 我应该如何反序列化以下JSON以跳过根元素并仅解析此JSON的内部。我想避免创建其他仅包含字段的3rd类。 因此,我只希望有以下两个类: 问题答案: 您可以为此使用库。 下面的代码将解决您的问题。

  • 问题内容: 我正在尝试使用Gson 反序列化a ,值的类型可以变化,值“ in_wanted”可以是a 或a 。 in_wanted为: in_wanted为: 每当“ in_wanted”的值为布尔值时,我都需要该对象,并且需要一个反序列化器以返回null。用Gson做到这一点的最佳方法是什么? 问题答案: 您可以使用自定义解串器来完成此操作。首先,我们应该创建可以表示您的JSON的数据模型。