Kotlin序列化:Multimap解析JSON空数组时抛出异常问题
解决Multimap字段解析JSON对象/空数组兼容问题
问题根源在于你的自定义序列化器仅处理了JSON对象格式的shop字段,未兼容空数组场景,导致解析时因预期对象却收到数组而抛出异常。以下是具体解决步骤:
1. 修改自定义反序列化器,兼容空数组判断
以Jackson为例,在自定义JsonDeserializer中先判断当前JSON Token类型,分场景处理:
import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import java.io.IOException; import java.util.List; public class ShopMultimapDeserializer extends JsonDeserializer<Multimap<Long, List<Long>>> { @Override public Multimap<Long, List<Long>> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { JsonToken currentToken = p.getCurrentToken(); // 处理空数组场景:跳过整个数组,返回空Multimap if (JsonToken.START_ARRAY.equals(currentToken)) { p.skipChildren(); // 跳过数组内所有元素 return ArrayListMultimap.create(); } // 原有对象格式解析逻辑 if (JsonToken.START_OBJECT.equals(currentToken)) { Multimap<Long, List<Long>> shopMultimap = ArrayListMultimap.create(); while (p.nextToken() != JsonToken.END_OBJECT) { String keyStr = p.getCurrentName(); Long shopId = Long.valueOf(keyStr); p.nextToken(); List<Long> goodsIds = p.readValueAs(List.class); shopMultimap.put(shopId, goodsIds); } return shopMultimap; } // 其他异常场景(如null)返回空Multimap,也可根据需求抛出异常 return ArrayListMultimap.create(); } }
2. 关联反序列化器到数据类字段
在Item类的shop字段上添加注解,指定使用上述自定义反序列化器:
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.google.common.collect.Multimap; import java.util.List; public class Item { // 其他字段... @JsonDeserialize(using = ShopMultimapDeserializer.class) private Multimap<Long, List<Long>> shop; // Getter、Setter... }
3. Gson场景的兼容实现(如果使用Gson)
若项目用Gson解析,可自定义TypeAdapter实现兼容:
import com.google.gson.TypeAdapter; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import java.io.IOException; import java.util.List; public class ShopMultimapTypeAdapter extends TypeAdapter<Multimap<Long, List<Long>>> { @Override public void write(JsonWriter out, Multimap<Long, List<Long>> value) throws IOException { // 序列化逻辑(按需实现) out.beginObject(); for (var entry : value.entries()) { out.name(entry.getKey().toString()); new com.google.gson.Gson().toJson(entry.getValue(), List.class, out); } out.endObject(); } @Override public Multimap<Long, List<Long>> read(JsonReader in) throws IOException { Multimap<Long, List<Long>> multimap = ArrayListMultimap.create(); JsonToken token = in.peek(); if (token == JsonToken.BEGIN_ARRAY) { in.beginArray(); while (in.hasNext()) { in.skipValue(); // 跳过数组内所有元素 } in.endArray(); return multimap; } if (token == JsonToken.BEGIN_OBJECT) { in.beginObject(); while (in.hasNext()) { String keyStr = in.nextName(); Long shopId = Long.parseLong(keyStr); List<Long> goodsIds = new com.google.gson.Gson().fromJson(in, List.class); multimap.put(shopId, goodsIds); } in.endObject(); return multimap; } return multimap; } }
注册TypeAdapter到Gson实例:
import com.google.gson.Gson; import com.google.gson.GsonBuilder; Gson gson = new GsonBuilder() .registerTypeAdapter(new com.google.common.reflect.TypeToken<Multimap<Long, List<Long>>>(){}.getType(), new ShopMultimapTypeAdapter()) .create();
内容的提问来源于stack exchange,提问作者RCH
相关产品推荐
相关产品推荐

