为了账号安全,请及时绑定邮箱和手机立即绑定

如何反/序列化具有动态类型属性的实例

如何反/序列化具有动态类型属性的实例

慕斯王 2022-07-20 16:58:26
使用 Jackson 序列化/反序列化 MyClass 实例的最佳方法是什么?class MyClass {    private String name;    private MyInterface classInstance;    // standard getters setters}属性 classInstance 可以是实现接口 MyInterface 的任意类型理想情况下,我希望 yaml 结构看起来像这样name: com.example.ClassEclassInstance:   value: 42  category: "fancy"请注意,“name”属性实际上包含“classInstance”属性内的对象的完全限定类型。
查看完整描述

1 回答

?
ABOUTYOU

TA贡献1812条经验 获得超5个赞

检查JsonTypeInfo注释。它可以为您生成class属性并YAML使用此属性反序列化有效负载。检查以下示例:


import com.fasterxml.jackson.annotation.JsonTypeInfo;

import com.fasterxml.jackson.databind.ObjectMapper;

import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;

import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;


import java.math.BigDecimal;


public class JsonApp {


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

        YAMLFactory yamlFactory = new YAMLFactory();

        yamlFactory.disable(YAMLGenerator.Feature.USE_NATIVE_TYPE_ID);


        ObjectMapper mapper = new ObjectMapper(yamlFactory);


        serialiseAndDeserialise(mapper, new MyValue());

        serialiseAndDeserialise(mapper, new MyBigDecimal());

    }


    private static void serialiseAndDeserialise(ObjectMapper mapper, MyInterface myInterface) throws java.io.IOException {

        MyClass myClass = new MyClass();

        myClass.setInstance(myInterface);


        String yaml = mapper.writeValueAsString(myClass);

        System.out.println(yaml);

        System.out.println(mapper.readValue(yaml, MyClass.class));

    }

}


class MyClass {


    @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, property = "name")

    private MyInterface instance;


    public MyInterface getInstance() {

        return instance;

    }


    public void setInstance(MyInterface instance) {

        this.instance = instance;

    }


    @Override

    public String toString() {

        return "MyClass{" +

                "instance=" + instance +

                '}';

    }

}


interface MyInterface {

}


class MyValue implements MyInterface {

    private int value = 42;

    private String category = "fancy";


    public int getValue() {

        return value;

    }


    public void setValue(int value) {

        this.value = value;

    }


    public String getCategory() {

        return category;

    }


    public void setCategory(String category) {

        this.category = category;

    }


    @Override

    public String toString() {

        return "MyValue{" +

                "value=" + value +

                ", category='" + category + '\'' +

                '}';

    }

}


class MyBigDecimal implements MyInterface {

    private BigDecimal pi = BigDecimal.valueOf(Math.PI);


    public BigDecimal getPi() {

        return pi;

    }


    public void setPi(BigDecimal pi) {

        this.pi = pi;

    }


    @Override

    public String toString() {

        return "MyBigDecimal{" +

                "pi=" + pi +

                '}';

    }

}

上面的代码打印:


---

instance:

  name: "com.celoxity.MyValue"

  value: 42

  category: "fancy"


MyClass{instance=MyValue{value=42, category='fancy'}}

---

instance:

  name: "com.celoxity.MyBigDecimal"

  pi: 3.141592653589793


MyClass{instance=MyBigDecimal{pi=3.141592653589793}}

如果您想移动到与仅更改注释name相同的级别:instance


@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "name")

输出将变为:


---

instance:

  value: 42

  category: "fancy"

name: "com.celoxity.MyValue"


MyClass{instance=MyValue{value=42, category='fancy'}}

---

instance:

  pi: 3.141592653589793

name: "com.celoxity.MyBigDecimal"


MyClass{instance=MyBigDecimal{pi=3.141592653589793}}

我更喜欢第一个,因为它通知name属性属于instance. 如果您name从注释中删除属性,Jackson则会使用这种类型的默认名称use- '@class'。


查看完整回答
反对 回复 2022-07-20
  • 1 回答
  • 0 关注
  • 88 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号