在jackson中配置了原始父类型之后,动态添加新的子类型

问题描述

我有一个超类from tkinter import * from tkinter import ttk inp = [{'Currency': 'EUR','Volume': '100','Country': 'SE'},{'Currency': 'GBR','Volume': '200',{'Currency': 'CAD','Volume': '300',{'Currency': 'EUR','Volume': '400','Country': 'DK'},] class Application(Tk): def __init__(self): Tk.__init__(self) self.title("Volume") combofr = Frame(self) combofr.pack(expand=True,fill=X) self.tree = ttk.Treeview(self,show='headings') columns = list(inp[0].keys()) self.filters = [] for col in columns: name = 'combo_' + col self.filters.append(name) setattr(self,name,ttk.ComboBox(combofr,values=[''] + sorted(set(x[col] for x in inp)),state="readonly")) getattr(self,name).pack(side=LEFT,expand=True,fill=X) getattr(self,name).bind('<<ComboBoxSelected>>',self.select_from_filters) self.tree["columns"] = columns self.tree.pack(expand=TRUE,fill=BOTH) for i in columns: self.tree.column(i,anchor="w") self.tree.heading(i,text=i,anchor="w") for i,row in enumerate(inp): self.tree.insert("","end",values=list(row.values())) def select_from_filters(self,event=None): self.tree.delete(*self.tree.get_children()) all_filter = lambda x: all(x[f.split('_')[-1]] == getattr(self,f).get() or getattr(self,f).get() == '' for f in self.filters) for row in inp: if all_filter(row): self.tree.insert("",values=list(row.values())) root = Application() root.mainloop() ,还有另外两个继承超类Field的类。

我想动态添加子类而不影响超类更改

Field

当字段是同一类Field的实例,而没有用于映射的className属性“ Field”时,我想以此方式使用映射

public class TestConfiguration {

private List<Field> fields;


}

当字段是子类ExtendedHierarchicalField的实例,然后将className属性“ ExtendedHierarchicalField”用于映射或通过任何其他方式映射对象时,我想以此方式使用映射

{
          "fields" : [ {
            "name" : "First_name","type" : {
              "fieldType" : {
                "name" : "string"
              }
            },"required" : true
          }]
}

解决方法

您可以使用杰克逊注释实现相同的目的。
将您的课程定义为:
Field.java

import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;

@JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS,property = "className")
@JsonSubTypes({
                      @JsonSubTypes.Type(value = SubField1.class),@JsonSubTypes.Type(value = SubField2.class)
              })
public class Field {
    public String name;
}

SubField1.java

public class SubField1 extends Field {
    public String subField1Property = "subField1Property value";
}

SubField2.java

public class SubField2 extends Field {
    public String subField2Property = "subField2Property value";
}

TestConfiguration.java

public class TestConfiguration {
    public List<Field> fields;
}

主要方法

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

    ObjectMapper mapper = new ObjectMapper();

    Field field = new Field();
    field.name = "main field";

    Field subField1 = new SubField1();
    subField1.name = "sub field 1";

    Field subField2 = new SubField2();
    subField2.name = "sub field 2";

    TestConfiguration testConfiguration = new TestConfiguration();
    testConfiguration.fields = Arrays.asList(field,subField1,subField2);

    String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(testConfiguration);
    System.out.println(json);
}

输出:

{
  "fields" : [ {
    "className" : ".Field","name" : "main field"
  },{
    "className" : ".SubField1","name" : "sub field 1","subField1Property" : "subField1Property value"
  },{
    "className" : ".SubField2","name" : "sub field 2","subField2Property" : "subField2Property value"
  } ]
}

注意:

  • className属性是强制性的(即使对于顶级类Field也是如此),原因是当您将相同的json反序列化为POJO而没有className属性时,这会让创建FieldSubField1SubField2的实例感到困惑。
  • 为方便起见,我在POJO中使用了公共财产。您应该只喜欢使用setter / getter的私有字段。