将平面 JSON 反序列化为复杂的 POJO
Deserialize flat JSON to complex POJO
我在 2.6.4 中使用 fasterxml 并通过我对给定输出没有影响的外部服务获得以下 JSON:
{
"name": "dunnosName",
"widthValue": 46.1,
"heightValue": 56.1,
"depthValue": 66.1,
"unit": "mm"
}
并希望将其映射到以下 POJO:
public class Dunno {
private String name;
private ValueWithUnit width;
private ValueWithUnit height;
private ValueWithUnit depth;
}
public class ValueWithUnit {
private Float value;
private String unit;
}
我的例外映射应如下所示:
name -> Dunno.name
widthValue -> Dunno.width.value
heightValue -> Dunno.height.value
depthValue -> Dunno.depth.value
unit -> Dunno.width.unit
unit -> Dunno.height.unit
unit -> Dunno.depth.unit
是否可以使用fasterxml实现预期的映射?如果是这样,我必须实施哪些 fasterxml 注释或 类 才能实现此映射?
public class Dunno {
private String name;
private ValueWithUnit width;
private ValueWithUnit height;
private ValueWithUnit depth;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ValueWithUnit getWidth() {
return width;
}
public void setWidth(ValueWithUnit width) {
this.width = width;
}
public ValueWithUnit getHeight() {
return height;
}
public void setHeight(ValueWithUnit height) {
this.height = height;
}
public ValueWithUnit getDepth() {
return depth;
}
public void setDepth(ValueWithUnit depth) {
this.depth = depth;
}
@Override
public String toString() {
return "Dunno{" +
"name='" + name + '\'' +
", width=" + width +
", height=" + height +
", depth=" + depth +
'}';
}
}
public class ValueWithUnit {
private Float value;
private String unit;
public ValueWithUnit(Float value, String unit) {
this.value = value;
this.unit = unit;
}
public Float getValue() {
return value;
}
public void setValue(Float value) {
this.value = value;
}
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
@Override
public String toString() {
return "ValueWithUnit{" +
"value=" + value +
", unit='" + unit + '\'' +
'}';
}
}
public class TempDunno {
private String name;
private Float widthValue;
private Float heightValue;
private Float depthValue;
private String unit;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Float getWidthValue() {
return widthValue;
}
public void setWidthValue(Float widthValue) {
this.widthValue = widthValue;
}
public Float getHeightValue() {
return heightValue;
}
public void setHeightValue(Float heightValue) {
this.heightValue = heightValue;
}
public Float getDepthValue() {
return depthValue;
}
public void setDepthValue(Float depthValue) {
this.depthValue = depthValue;
}
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
@Override
public String toString() {
return "TempDunno{" +
"name='" + name + '\'' +
", widthValue=" + widthValue +
", heightValue=" + heightValue +
", depthValue=" + depthValue +
", unit='" + unit + '\'' +
'}';
}
}
public class Main {
public static void main(String[] args) throws IOException {
String json = "{\n" +
" \"name\": \"dunnosName\",\n" +
" \"widthValue\": 46.1,\n" +
" \"heightValue\": 56.1,\n" +
" \"depthValue\": 66.1,\n" +
" \"unit\": \"mm\"\n" +
"}";
System.out.println(getDunno(json));
}
private static Dunno getDunno(String json) throws IOException {
ObjectMapper mapper = new ObjectMapper();
TempDunno tmp = mapper.readValue(json, TempDunno.class);
Dunno dunno = new Dunno();
dunno.setName(tmp.getName());
dunno.setHeight(new ValueWithUnit(tmp.getHeightValue(), tmp.getUnit()));
dunno.setWidth(new ValueWithUnit(tmp.getWidthValue(), tmp.getUnit()));
dunno.setDepth(new ValueWithUnit(tmp.getDepthValue(), tmp.getUnit()));
return dunno;
}
}
您不需要过渡 TempDunno
。你需要一个Custom Deserializer。这是您将使用的教科书示例。将以下注释添加到 Dunno
class:
@JsonDeserialize(using = DunnoDeserializer.class)
在这里,还有输入验证:
@SuppressWarnings("serial")
public class DunnoDeserializer extends StdDeserializer<Dunno>
{
public DunnoDeserializer()
{
this(null);
}
public DunnoDeserializer(Class<?> vc)
{
super(vc);
}
@Override
public Dunno deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException
{
Dunno dunno = new Dunno();
// first parse the input into a map, which is more convenient to work with
@SuppressWarnings("unchecked")
Map<String, Object> values = jp.getCodec().readValue(jp, Map.class);
dunno.name = values.containsKey("name") ? values.get("name").toString() : "empty";
String unit = values.containsKey("unit") ? values.get("unit").toString() : "default-units";
if (values.containsKey("widthValue")) {
dunno.width = new ValueWithUnit();
dunno.width.value = ((Number)values.get("widthValue")).floatValue();
dunno.width.unit = unit;
}
if (values.containsKey("heightValue")) {
dunno.height = new ValueWithUnit();
dunno.height.value = ((Number)values.get("heightValue")).floatValue();
dunno.height.unit = unit;
}
if (values.containsKey("depthValue")) {
dunno.depth = new ValueWithUnit();
dunno.depth.value = ((Number)values.get("depthValue")).floatValue();
dunno.depth.unit = unit;
}
System.out.println(values);
values.values().forEach(v -> System.out.println(v.getClass()));
return dunno;
}
}
测试方法:
public static void main(String[] args)
{
String jsonString = "{ \"name\": \"dunnosName\"," + "\"widthValue\": 46.1," + "\"heightValue\": 56.1,"
+ "\"depthValue\": 66.1," + "\"unit\": \"mm\"}";
ObjectMapper mapper = new ObjectMapper();
try {
Dunno d = (Dunno)mapper.readValue(jsonString, Dunno.class);
System.out.format("%s: %.2f(%s) %.2f(%s) %.2f(%s)",
d.name, d.width.value, d.width.unit, d.height.value, d.height.unit, d.depth.value, d.depth.unit);
} catch (IOException e) {
e.printStackTrace();
}
}
给出预期输出:
dunnosName: 46.10(mm) 56.10(mm) 66.10(mm)
我在 2.6.4 中使用 fasterxml 并通过我对给定输出没有影响的外部服务获得以下 JSON:
{
"name": "dunnosName",
"widthValue": 46.1,
"heightValue": 56.1,
"depthValue": 66.1,
"unit": "mm"
}
并希望将其映射到以下 POJO:
public class Dunno {
private String name;
private ValueWithUnit width;
private ValueWithUnit height;
private ValueWithUnit depth;
}
public class ValueWithUnit {
private Float value;
private String unit;
}
我的例外映射应如下所示:
name -> Dunno.name
widthValue -> Dunno.width.value
heightValue -> Dunno.height.value
depthValue -> Dunno.depth.value
unit -> Dunno.width.unit
unit -> Dunno.height.unit
unit -> Dunno.depth.unit
是否可以使用fasterxml实现预期的映射?如果是这样,我必须实施哪些 fasterxml 注释或 类 才能实现此映射?
public class Dunno {
private String name;
private ValueWithUnit width;
private ValueWithUnit height;
private ValueWithUnit depth;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ValueWithUnit getWidth() {
return width;
}
public void setWidth(ValueWithUnit width) {
this.width = width;
}
public ValueWithUnit getHeight() {
return height;
}
public void setHeight(ValueWithUnit height) {
this.height = height;
}
public ValueWithUnit getDepth() {
return depth;
}
public void setDepth(ValueWithUnit depth) {
this.depth = depth;
}
@Override
public String toString() {
return "Dunno{" +
"name='" + name + '\'' +
", width=" + width +
", height=" + height +
", depth=" + depth +
'}';
}
}
public class ValueWithUnit {
private Float value;
private String unit;
public ValueWithUnit(Float value, String unit) {
this.value = value;
this.unit = unit;
}
public Float getValue() {
return value;
}
public void setValue(Float value) {
this.value = value;
}
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
@Override
public String toString() {
return "ValueWithUnit{" +
"value=" + value +
", unit='" + unit + '\'' +
'}';
}
}
public class TempDunno {
private String name;
private Float widthValue;
private Float heightValue;
private Float depthValue;
private String unit;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Float getWidthValue() {
return widthValue;
}
public void setWidthValue(Float widthValue) {
this.widthValue = widthValue;
}
public Float getHeightValue() {
return heightValue;
}
public void setHeightValue(Float heightValue) {
this.heightValue = heightValue;
}
public Float getDepthValue() {
return depthValue;
}
public void setDepthValue(Float depthValue) {
this.depthValue = depthValue;
}
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
@Override
public String toString() {
return "TempDunno{" +
"name='" + name + '\'' +
", widthValue=" + widthValue +
", heightValue=" + heightValue +
", depthValue=" + depthValue +
", unit='" + unit + '\'' +
'}';
}
}
public class Main {
public static void main(String[] args) throws IOException {
String json = "{\n" +
" \"name\": \"dunnosName\",\n" +
" \"widthValue\": 46.1,\n" +
" \"heightValue\": 56.1,\n" +
" \"depthValue\": 66.1,\n" +
" \"unit\": \"mm\"\n" +
"}";
System.out.println(getDunno(json));
}
private static Dunno getDunno(String json) throws IOException {
ObjectMapper mapper = new ObjectMapper();
TempDunno tmp = mapper.readValue(json, TempDunno.class);
Dunno dunno = new Dunno();
dunno.setName(tmp.getName());
dunno.setHeight(new ValueWithUnit(tmp.getHeightValue(), tmp.getUnit()));
dunno.setWidth(new ValueWithUnit(tmp.getWidthValue(), tmp.getUnit()));
dunno.setDepth(new ValueWithUnit(tmp.getDepthValue(), tmp.getUnit()));
return dunno;
}
}
您不需要过渡 TempDunno
。你需要一个Custom Deserializer。这是您将使用的教科书示例。将以下注释添加到 Dunno
class:
@JsonDeserialize(using = DunnoDeserializer.class)
在这里,还有输入验证:
@SuppressWarnings("serial")
public class DunnoDeserializer extends StdDeserializer<Dunno>
{
public DunnoDeserializer()
{
this(null);
}
public DunnoDeserializer(Class<?> vc)
{
super(vc);
}
@Override
public Dunno deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException
{
Dunno dunno = new Dunno();
// first parse the input into a map, which is more convenient to work with
@SuppressWarnings("unchecked")
Map<String, Object> values = jp.getCodec().readValue(jp, Map.class);
dunno.name = values.containsKey("name") ? values.get("name").toString() : "empty";
String unit = values.containsKey("unit") ? values.get("unit").toString() : "default-units";
if (values.containsKey("widthValue")) {
dunno.width = new ValueWithUnit();
dunno.width.value = ((Number)values.get("widthValue")).floatValue();
dunno.width.unit = unit;
}
if (values.containsKey("heightValue")) {
dunno.height = new ValueWithUnit();
dunno.height.value = ((Number)values.get("heightValue")).floatValue();
dunno.height.unit = unit;
}
if (values.containsKey("depthValue")) {
dunno.depth = new ValueWithUnit();
dunno.depth.value = ((Number)values.get("depthValue")).floatValue();
dunno.depth.unit = unit;
}
System.out.println(values);
values.values().forEach(v -> System.out.println(v.getClass()));
return dunno;
}
}
测试方法:
public static void main(String[] args)
{
String jsonString = "{ \"name\": \"dunnosName\"," + "\"widthValue\": 46.1," + "\"heightValue\": 56.1,"
+ "\"depthValue\": 66.1," + "\"unit\": \"mm\"}";
ObjectMapper mapper = new ObjectMapper();
try {
Dunno d = (Dunno)mapper.readValue(jsonString, Dunno.class);
System.out.format("%s: %.2f(%s) %.2f(%s) %.2f(%s)",
d.name, d.width.value, d.width.unit, d.height.value, d.height.unit, d.depth.value, d.depth.unit);
} catch (IOException e) {
e.printStackTrace();
}
}
给出预期输出:
dunnosName: 46.10(mm) 56.10(mm) 66.10(mm)