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

Gson转换JSON报错:Expected a string but was BEGIN_OBJECT 求助

问题

调用第三方API获取JSON数据时,System.out.println(jsonCep.toString())能正常打印JSON结构,但执行UsuarioPessoa user = new Gson().fromJson(jsonCep.toString(), UsuarioPessoa.class);时,Gson抛出错误:Expected a string but was BEGIN_OBJECT。

打印出的JSON内容

{"status":{"code":200,"message":"Ok"},"data":[],"page":{"next":"https://sandbox-api.arquivei.com.br/v1/nfe/received?cnpj%5C%5B0%5C%5D=34174654000153&cursor=0&limit=50%22,%22previous%22:%22https://sandbox-api.arquivei.com.br/v1/nfe/received?cnpj%5C%5B0%5C%5D=34174654000153&cursor=0&limit=50%22%7D,%22count%22:0,%22signature%22:%224f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945"}

完整代码

public void pesquisaCode() {
    try {
        String code="34174654000153";
        String apikey = "69087091f4d28d29e5c2d326831c86bfc7903634";
        String apiID="b79cbfedaf0d9b0be1a3a2d7263fdc61c94e2311";
        URL url = new URL("https://sandbox-api.arquivei.com.br/v1/nfe/received?cnpj[]="+code+"");
        URLConnection connection = url.openConnection();
        connection.setRequestProperty("Content-Type","application/json");
        connection.setRequestProperty("X-API-KEY", apikey);
        connection.setRequestProperty("X-API-ID", apiID);
        ((HttpURLConnection) connection).setRequestMethod("GET");
        connection.setDoOutput(true);
        InputStream is = connection.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));

        String cep="";
        StringBuilder jsonCep = new StringBuilder();
        while((cep = br.readLine()) != null) {
            jsonCep.append(cep);
        }
        System.out.println(jsonCep.toString());
        UsuarioPessoa user = new Gson().fromJson(jsonCep.toString(), UsuarioPessoa.class);
    }   
    catch (Exception e) {
        e.printStackTrace();
    }
}

API返回的标准JSON(Postman中结果)

{
  "status": {
    "code": 200,
    "message": "Ok"
  },
  "data": [
    
  ],
  "page": {
    "next": "https:\/\/sandbox-api.arquivei.com.br\/v1\/nfe\/received?cnpj[0]=34174654000153&cursor=0&limit=50",
    "previous": "https:\/\/sandbox-api.arquivei.com.br\/v1\/nfe\/received?cnpj[0]=34174654000153&cursor=0&limit=50"
  },
  "count": 0,
  "signature": "4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945"
}

解决方案

1. 修复JSON格式损坏问题

对比打印的JSON和Postman返回的标准JSON,能发现打印的JSON存在结构损坏:page字段的next值错误包含了后续的","previous":"..."等内容,导致整个JSON语法混乱,Gson无法正常解析。

问题根源是手动拼接URL时,cnpj[]参数未正确编码,服务器返回了格式错误的JSON。修复方式如下:

// 使用URLEncoder对参数进行正确编码
String encodedCode = URLEncoder.encode(code, "UTF-8");
URL url = new URL("https://sandbox-api.arquivei.com.br/v1/nfe/received?cnpj[]=" + encodedCode);

或者用更规范的URL构建方式(需引入Java EE的javax.ws.rs-api包):

URI uri = new UriBuilder()
        .scheme("https")
        .host("sandbox-api.arquivei.com.br")
        .path("/v1/nfe/received")
        .queryParam("cnpj[]", code)
        .build();
URL url = uri.toURL();

2. 匹配实体类与JSON结构

Gson抛出Expected a string but was BEGIN_OBJECT的核心原因是UsuarioPessoa类的字段定义与JSON结构不匹配。比如JSON中status是嵌套对象,但如果你的实体类将status定义为String类型,就会触发该错误。

需根据API返回的JSON结构,定义正确的实体类:

// 顶层实体类,对应整个JSON结构
public class ApiResponse {
    private Status status;
    private List<Object> data; // 若data有具体结构,替换为对应实体类
    private Page page;
    private int count;
    private String signature;

    // 嵌套的Status类
    public static class Status {
        private int code;
        private String message;
        // getter、setter、无参构造方法
    }

    // 嵌套的Page类
    public static class Page {
        private String next;
        private String previous;
        // getter、setter、无参构造方法
    }

    // 顶层类的getter、setter、无参构造方法
}

之后用该类进行解析:

ApiResponse response = new Gson().fromJson(jsonCep.toString(), ApiResponse.class);

3. 优化HTTP请求处理

手动使用URLConnection易出现编码、流处理等问题,建议使用成熟的HTTP客户端库(如OkHttp)简化请求:

OkHttpClient client = new OkHttpClient();

Request request = new Request.Builder()
        .url("https://sandbox-api.arquivei.com.br/v1/nfe/received?cnpj[]=" + code)
        .addHeader("Content-Type", "application/json")
        .addHeader("X-API-KEY", apikey)
        .addHeader("X-API-ID", apiID)
        .build();

try (Response response = client.newCall(request).execute()) {
    String json = response.body().string();
    ApiResponse apiResponse = new Gson().fromJson(json, ApiResponse.class);
} catch (IOException e) {
    e.printStackTrace();
}

内容的提问来源于stack exchange,提问作者Lucas Baur

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 13:35:19