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

使用指定旧HTTP库时,Gson解析含字节数组的JSON出现「期望对象却得到数组」错误的原因及解决疑问

问题分析与解决方案

首先看你的报错信息Expected BEGIN_OBJECT but was BEGIN_ARRAY,这已经很明确了——你返回的JSON是一个数组(外层是[]),但你却试图把它解析成单个PDFResponse对象,这是导致错误的直接原因。先解决这个核心问题,再处理字节数组的适配。

第一步:修复数组解析的问题

你的接口返回的是包含单个PDFResponse对象的JSON数组,所以需要把解析代码改成解析数组类型,两种方式任选:

方式1:解析为List<PDFResponse>

@Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
    Type listType = new TypeToken<List<PDFResponse>>() {}.getType();
    List<PDFResponse> pdfResponseList = gson.fromJson(new String(responseBody), listType);
    // 取第一个元素使用(根据业务确认数组非空)
    if (!pdfResponseList.isEmpty()) {
        PDFResponse pdfResponse = pdfResponseList.get(0);
        Debug.i("pdf: success ");
    }
}

方式2:解析为PDFResponse数组

@Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
    PDFResponse[] pdfResponses = gson.fromJson(new String(responseBody), PDFResponse[].class);
    // 取第一个元素使用(根据业务确认数组非空)
    if (pdfResponses.length > 0) {
        PDFResponse pdfResponse = pdfResponses[0];
        Debug.i("pdf: success ");
    }
}

第二步:处理byte[]字段的解析问题

解决数组问题后,你会发现imgBinaryData字段仍无法正确解析——因为JSON里的imgBinaryData是整数数组(比如[-1,40,-1]),而Gson默认不会自动把int[]转成byte[](两者取值范围不同:byte是-128到127,int范围更大)。这里提供两种解决方案:

方案A:修改POJO字段类型,手动转换

把POJO里的byte[] imgBinaryData改成int[]或List<Integer>,然后在需要使用时手动转成byte数组:

public class PDFResponse {
    private Integer pdfconfigid;
    @SerializedName("LocationName") // 匹配JSON里的大写键
    private String locationName;
    @SerializedName("imgBinaryData")
    private int[] imgBinaryData; // 改成int数组
    // 其他字段同理添加@SerializedName匹配JSON键
    @SerializedName("LocationCode")
    private String locationCode;
    @SerializedName("ActiveStatus")
    private String activeStatus;
    // ...省略getter/setter

    // 手动转换为byte数组的方法
    public byte[] getImgBinaryDataAsBytes() {
        if (imgBinaryData == null) return null;
        byte[] bytes = new byte[imgBinaryData.length];
        for (int i = 0; i < imgBinaryData.length; i++) {
            // 注意:若JSON中的int值超出byte范围会自动截断,需根据业务确认是否允许
            bytes[i] = (byte) imgBinaryData[i];
        }
        return bytes;
    }
}

方案B:自定义Gson TypeAdapter,自动转换

如果不想修改POJO字段类型,可以写一个自定义适配器处理int数组到byte数组的转换:

public class ByteArrayTypeAdapter extends TypeAdapter<byte[]> {
    @Override
    public void write(JsonWriter out, byte[] value) throws IOException {
        if (value == null) {
            out.nullValue();
            return;
        }
        out.beginArray();
        for (byte b : value) {
            out.value(b & 0xFF); // 转成无符号int输出,避免负数序列化问题
        }
        out.endArray();
    }

    @Override
    public byte[] read(JsonReader in) throws IOException {
        if (in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
        }
        in.beginArray();
        List<Byte> byteList = new ArrayList<>();
        while (in.hasNext()) {
            int intValue = in.nextInt();
            // 可添加逻辑处理超出byte范围的int值,这里直接强制转换
            byteList.add((byte) intValue);
        }
        in.endArray();
        // 转为byte数组返回
        byte[] result = new byte[byteList.size()];
        for (int i = 0; i < result.length; i++) {
            result[i] = byteList.get(i);
        }
        return result;
    }
}

然后创建Gson实例时注册这个适配器:

Gson gson = new GsonBuilder()
        .registerTypeAdapter(byte[].class, new ByteArrayTypeAdapter())
        .create();

这样就能直接把JSON里的int数组解析为POJO中的byte[]了。

最后补充:你的JSON键是大写开头(如LocationName),POJO字段是小写开头,一定要给这些字段添加@SerializedName注解,否则Gson无法正确映射字段。

内容的提问来源于stack exchange,提问作者Pemba Tamang

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 22:42:30