1

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 Answer 1

1

@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:

Sign up to request clarification or add additional context in comments.

2 Comments

thanks for replying .. is there any other solution to match the JSON without changing it? another way to solve it I'm thinking about create attribute with type of resistance and m1 instead of device but it will force me to add attribute for each device will be added to the system.
The only other way would be to create a custom deserializer. But is changing the JSON impossible? The way you are structuring your JSON is making your life hard instead of easier, so consider changing it instead of working around it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.