binding a child object from JSON to parent attribute java

Viewed 583

I have a class called Component that contains some attributes including an object of Device class which is a base class for some classes such as Resistance and M1 and I have to read a JSON file for components and check the type of the device Resistance or M1 then map it to the right class I tried to use JSON annotation but I'm still getting errors!

Here are my classes Component Class:

public class Component {
private String type;
private String id;


@JsonProperty
private Device device;
@JsonProperty("netlist")
private HashMap<String,String> netlist;

public Component() {
}

public Component(String type, String id, Device device, HashMap<String, String> netList) {
    this.type = type;
    this.id = id;
    this.device = device;
    this.netlist = netList;
}

public String getType() {
    return type;
}

public void setType(String type) {
    this.type = type;
}

public String getId() {
    return id;
}

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

public Device getDevice() {
    return device;
}

public void setDevice(Device device) {
    this.device = device;
}
public HashMap<String, String> getNetlist() {
    return netlist;
}

public void setNetlist(HashMap<String, String> netlist) {
    this.netlist = netlist;
}

@Override
public String toString() {
    return "type='" + type + '\'' +
            ", id='" + id + '\'' +
            ", "+device.toString()+
            ", netList=" + netlist ;
}
}

Device Class:

public abstract class Device {
@JsonProperty("default")
protected int defaultValue;
protected int min;
protected int max;

public Device() {
}

public Device(int defaultValue, int min, int max) {
    this.defaultValue = defaultValue;
    this.min = min;
    this.max = max;
}

public int getDefaultValue() {
    return defaultValue;
}

public void setDefaultValue(int defaultValue) {
    this.defaultValue = defaultValue;
}

public int getMin() {
    return min;
}

public void setMin(int min) {
    this.min = min;
}

public int getMax() {
    return max;
}

public void setMax(int max) {
    this.max = max;
}


}

Resistance :

    @JsonTypeName("resistance")
public class Resistance extends Device {
    public Resistance() {
    }
@Override
public String toString() {
    return "resistance{" +
            "default=" + defaultValue +
            ", min=" + min +
            ", max=" + max +
            '}';
}
}

M1 Class:

@JsonTypeName(value = "m(1)")
public class M1 extends Device {
    @Override
    public String toString() {
        return "m(1){" +
                "default=" + defaultValue +
                ", min=" + min +
                ", max=" + max +
                '}';
    }
}

and this is a simple JSON file:

"components": [
  {
    "type": "resistor",
    "id": "res1",
    "resistance": {
      "default": 100,
      "min": 10,
      "max": 1000
    },
    "netlist": {
      "t1": "vdd",
      "t2": "n1"
    }
  },
  {
    "type": "nmos",
    "id": "m1",
    "m(l)": {
      "deafult": 1.5,
      "min": 1,
      "max": 2
    },
    "netlist": {
      "drain": "n1",
      "gate": "vin",
      "source": "vss"
    }
  }
]

Thanks in advance

1 Answers

@JsonTypeName does not do what you think it does. In its reference documentation you can read:

Annotation used for binding logical name that the annotated class has. Used with JsonTypeInfo (and specifically its JsonTypeInfo.use() property) to establish relationship between type names and types.

This means that you are missing key annotations in Device (@JsonTypeInfo and @JsonSubTypes) so that Jackson knows how to read the JSON you are providing:

@JsonTypeInfo(
  use = JsonTypeInfo.Id.NAME, 
  include = JsonTypeInfo.As.PROPERTY, 
  property = "type")
@JsonSubTypes({ 
  @Type(value = Resistance.class, name = "resistance"), 
  @Type(value = M1.class, name = "m1") 
})
public abstract class Device {
    (...)
}

With this you can get rid of @JsonTypeName in Resistance and M1.

However, this is not enough. You also need to change your JSON to match Component properties (resistance and m(1) must be renamed to device) and you also need to add a type to this device property to match @JsonTypeInfo and @JsonSubTypes:

"components": [
  {
    "type": "resistor",
    "id": "res1",
    "device": {
      "type": "resistance",
      "default": 100,
      "min": 10,
      "max": 1000
    },
    "netlist": {
      "t1": "vdd",
      "t2": "n1"
    }
  },
  {
    "type": "nmos",
    "id": "m1",
    "device": {
      "type": "m1",
      "deafult": 1.5,
      "min": 1,
      "max": 2
    },
    "netlist": {
      "drain": "n1",
      "gate": "vin",
      "source": "vss"
    }
  }
]

You can read more about this in the following online resources:

Related