You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 17:52:53