【问题标题】:How to parse json with recursive lists of objects with Gson?如何使用 Gson 解析带有递归对象列表的 json?
【发布时间】:2023-04-04 13:15:01
【问题描述】:

我需要使用 Gson 将传入的 json 消息解析为 Java 对象。 “MessageBody”类应该用于提供 Gson.fromJson(json, MessageBody.class);

json 消息如下所示。

第一层有三个静态字段。第三个字段(“fields”)是“DataField”对象的列表。

DataField 对象具有类型和值字段。 它的价值可能是异质的。预期类型为:“String”、“int”、“boolean”和“HashMap”。

{
    "eventId": "abc",
    "customerId": "abc",
    "fields": {
        "eventDateTime": {
            "type": "datetime",
            "value": "2019-05-03T10:15:30Z"
        },
        "eventCorrelationID": {
            "type": "string",
            "value": "abc"
        },
        "additionalAttributes": {
            "type": "collection",
            "value": {
                "additionalAttribute1": {
                    "value": "abc",
                    "type": "string"
                },
                "additionalAttribute2": {
                    "value": "abc",
                    "type": "string"
                }
            }
        }
    }
}
public class MessageBody {
    private String eventId;
    private String customerId;
    private HashMap<String, DataField> fields;

    public String getEventId() {
        return eventId;
    }

    public void setEventId(String eventId) {
        this.eventId = eventId;
    }

    public String getCustomerId() {
        return customerId;
    }

    public void setCustomerId(String customerId) {
        this.customerId = customerId;
    }

    public HashMap<String, DataField> getFields() {
        return fields;
    }

    public void setFields(HashMap<String, DataField> fields) {
        this.fields = fields;
    }

    public class DataField {
        private Object value;
        private String type;

        public Object getValue() {
            return value;
        }

        public void setValue(Object value) {
            this.value = value;
        }

        public String getType() {
            return type;
        }

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

使用上述类的解析适用于除“additionalAttributes”下的嵌套 DataField 列表之外的所有对象。

它们产生一个 LinkedHashTreeMap 对象。不幸的是,无法将其转换为另一个 DataField 的 HashMap。

如何处理异构对象中的嵌套/递归列表?

如何使以下语句起作用? :-)

HashMap<String, DataField> addAttrs = (HashMap<String, DataField>) messageBody.getFields().get("additionalAttributes").getValue();

【问题讨论】:

  • 你的问题解决了吗?

标签: java json parsing gson


【解决方案1】:

使用结构,希望对您有所帮助:

 public class MessageBody {
     private String eventId;
     private String customerId;
     private DataFields datafields;

    }

     public class DataFields {
        private DataField eventDateTime;
        private DataField eventCorrelationID;
        pprivate HashMap<String, DataField> additionalAttributes;

     }

    public class DataField {
        private Object value;
        private String type;
    }

【讨论】:

    【解决方案2】:

    您需要实现自定义JsonDeserializer。您拥有类型信息,这可能有助于区分正确的类型。下面的实现不使用它,但如果你有多个集合类型,你可以扩展它:

    class DataFieldJsonDeserializer implements JsonDeserializer<DataField> {
    
        private final Type collectionType = new TypeToken<Map<String, DataField>>() {}.getType();
    
        @Override
        public DataField deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
            throws JsonParseException {
            DataField dataField = new DataField();
    
            JsonObject jsonObject = json.getAsJsonObject();
            JsonPrimitive type = jsonObject.getAsJsonPrimitive("type");
            dataField.setType(type.getAsString());
    
            JsonElement value = jsonObject.get("value");
            if (value.isJsonPrimitive()) {
                dataField.setValue(value.getAsJsonPrimitive().getAsString());
            } else {
                Object result = context.deserialize(value, collectionType);
                dataField.setValue(result);
            }
    
            return dataField;
        }
    }
    

    注册适配器:

    @JsonAdapter(DataFieldJsonDeserializer.class)
    public static class DataField {
    

    示例用法:

    import com.google.gson.Gson;
    import com.google.gson.GsonBuilder;
    import com.google.gson.JsonDeserializationContext;
    import com.google.gson.JsonDeserializer;
    import com.google.gson.JsonElement;
    import com.google.gson.JsonObject;
    import com.google.gson.JsonParseException;
    import com.google.gson.JsonPrimitive;
    import com.google.gson.annotations.JsonAdapter;
    import com.google.gson.reflect.TypeToken;
    import java.lang.reflect.Type;
    import java.util.HashMap;
    import java.util.Map;
    
    public class Test {
    
        public static void main(String[] args) {
    
            Gson gson = new GsonBuilder().create();
            MessageBody messageBody = gson.fromJson(json, MessageBody.class);
    
            Map<String, DataField> addAttrs = (Map<String, DataField>) messageBody.getFields()
                .get("additionalAttributes").getValue();
            System.out.println(addAttrs);
        }
    }
    

    打印:

    {additionalAttribute1=DataField{value=abc, type='string'}, additionalAttribute2=DataField{value=abc, type='string'}}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-21
      • 1970-01-01
      • 1970-01-01
      • 2016-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多