gson反序列化自定义对象的Map

jm2pwxwz  于 2021-07-06  发布在  Java
关注(0)|答案(1)|浏览(545)

我正在尝试使用gson反序列化map<eventcontext.key,object>。
我最初试图通过

System.out.println(eventContextMapSerialized);
    Map<EventContext.Key, Object> deserializedMap = gson.fromJson(eventContextMapSerialized, HashMap.class);
    LogisticService logisticService = (LogisticService) deserializedMap.get(EventContext.Key.LOGISTIC_SERVICE);
    System.out.println(deserializedMap.get(EventContext.Key.LOGISTIC_SERVICE));
    System.out.println(logisticService);

这给了我输出

[junit] {"LOGISTIC_SERVICE":{"serviceId":"dummy_id","serviceVersion":1,"serviceProviderRefId":{"id":"dummy_id"},"contract":{"invoiceCreator":"USPS","maxDaysToReceiveInvoice":180},"cancelled":false,"serviceConsumer":{"id":"SERVICE_CONSUMER_ID_1"},"serviceProvider":{"id":"USPS"},"plannedServiceTimePeriod":{"startTime":"Jan 1, 1970 5:30:00 AM"},"planner":"ATROPS"},"PLATFORM_SERVICE_ID":"TestPlatformServiceId"}
[junit] null
[junit] null

因此,即使序列化字符串包含logisticservice类型的对象,当我尝试获取它时,也会得到null。
因此,我尝试使用 fromJson 它以类型作为参数。

Type type = new TypeToken<Map<EventContext.Key, Object>>(){}.getType();
    Map<EventContext.Key, Object> eventContextMapDeserialized = gson.fromJson(eventContextMapSerialized, type);
    System.out.println("Event Context Map Deserialized is : " + eventContextMapDeserialized);

    System.out.println(eventContextMapDeserialized.get(EventContext.Key.LOGISTIC_SERVICE).getClass());
    LogisticService logisticServiceFromMap = (LogisticService) eventContextMapDeserialized.get(EventContext.Key.LOGISTIC_SERVICE);
    System.out.println("Logistic Service from Event Context Map : " + logisticServiceFromMap);
    System.out.println("Direct Logistic Service : " + eventContextDeserialized.get(EventContext.Key.LOGISTIC_SERVICE));

输出的结果,

[junit] Event Context Map Deserialized is : {LOGISTIC_SERVICE={serviceId=dummy_id, serviceVersion=1.0, serviceProviderRefId={id=dummy_id}, contract={invoiceCreator=USPS, maxDaysToReceiveInvoice=180.0}, cancelled=false, serviceConsumer={id=SERVICE_CONSUMER_ID_1}, serviceProvider={id=USPS}, plannedServiceTimePeriod={startTime=Jan 1, 1970 5:30:00 AM}, planner=ATROPS}, PLATFORM_SERVICE_ID=TestPlatformServiceId}
[junit] class com.google.gson.internal.LinkedTreeMap
[junit] Testcase: testPayloadDeserialize took 10.812 sec
[junit]     Caused an ERROR
[junit] com.google.gson.internal.LinkedTreeMap cannot be cast to com.amazon.transportation.tfs.contapservice.sdk.model.LogisticService
[junit] java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.amazon.transportation.tfs.contapservice.sdk.model.LogisticService

基本上,在我想投的地方爆炸 (LogisticService) eventContextMapDeserialized.get(EventContext.Key.LOGISTIC_SERVICE); 我不明白为什么在第一种情况下输出为空,在第二种情况下,即使给出了类型,它仍然崩溃。

klr1opcd

klr1opcd1#

正如在注解中指出的,当您反序列化 HashMap.class 或者 TypeToken<Map<EventContext.Key, Object>> gson无法知道您期望的值类型。相反,它看到数据包含一个json对象,并将其反序列化为java Map 默认情况下(gson的内部 Map 实施是 LinkedTreeMap ).
因为看起来您正在处理一个异构Map,所以您需要采取另一种方法。一种解决办法是直接使用 JsonReader 然后根据json对象成员名称分别解析它们:

Gson gson = new Gson();
LogisticService logisticService = null;

JsonReader jsonReader = new JsonReader(json);
jsonReader.beginObject();
while (jsonReader.hasNext()) {
    String name = jsonReader.nextName();
    if (name.equals(EventContext.Key.LOGISTIC_SERVICE.name()) {
        if (logisticService != null) {
            // Duplicate member -> malicious or malformed JSON, throw exception
            ...
        }
        logisticService = gson.fromJson(jsonReader, LogisticService.class);
    }
    else {
        // Skip value or parse it in a different way
        jsonReader.skipValue();
    }
}
jsonReader.endObject();

或者,当这些数据是更大的json文档的一部分时,您也可以将这些代码放入 TypeAdapterFactory 创建 Gson 示例使用 GsonBuilder 你在上面注册了工厂。
或者,您可以创建一个单独的类来建模 Map ,例如:

class EventData {
    // Use Gson's @SerializedName annotation to not use the field name
    @SerializedName("LOGISTIC_SERVICE")
    public LogisticService logisticService;
}

Gson gson = new Gson();
EventData eventData = gson.fromJson(EventData.class);
LogisticService logisticService = eventData.logisticService;

相关问题