如何使用Gson结合实体类解析含其他数据类型的JSON数组
正确使用Gson解析包含数组与普通字段的JSON方案
待解析的JSON结构
{ "results": [ { "c": 75.0875, "h": 75.15, "l": 73.7975, "n": 1, "o": 74.06, "t": 1577941200000, "v": 135647456, "vw": 74.6099 }, { "c": 74.3575, "h": 75.145, "l": 74.125, "n": 1, "o": 74.2875, "t": 1578027600000, "v": 146535512, "vw": 74.7026 } ], "status": "OK", "ticker": "AAPL" }
现有代码与问题
主类代码
Transcript transcript = new Transcript(); Gson gson = new Gson(); // HTTP Requests here transcript = gson.fromJson(getResponse.body(), Transcript.class); // "status" verification System.out.println(transcript.getResults());
Transcript类(错误写法)
public class Transcript { public Type results = new TypeToken<ArrayList<DataObject>>(){}.getType(); public String ticker = "AAPL"; public String status; // Getters and setters too }
DataObject类(错误写法)
public class DataObject { public String tag; public double value; public DataObject(String tag, double value){ this.tag = tag; this.value = value; } public String toString() { return "tag = " + tag + ", value = " + value; } }
遇到的错误
- 当前核心错误:
Caused by: com.google.gson.JsonIOException: Interfaces can't be instantiated! Register an InstanceCreator or a TypeAdapter for this type. Interface name: java.lang.reflect.Type
- 将字段改为private时的错误:
com.google.gson.JsonIOException: Failed making field 'piemanray314.testingjavafx.testingjavafx.Transcript#results' accessible; either increase its visibility or write a custom TypeAdapter for its declaring type.
正确解决方案
1. 修正DataObject类
JSON的results数组内对象的字段是c、h、l等,需将DataObject字段名与JSON严格对应,同时保留无参构造(Gson依赖它实例化对象):
public class DataObject { public double c; public double h; public double l; public int n; public double o; public long t; public long v; public double vw; // 必须保留无参构造 public DataObject() {} @Override public String toString() { return "c=" + c + ", h=" + h + ", l=" + l + ", n=" + n + ", o=" + o + ", t=" + t + ", v=" + v + ", vw=" + vw; } }
2. 修正Transcript类
直接用List<DataObject>声明results字段,无需使用Type类型,同时规范字段访问权限:
import java.util.List; public class Transcript { private List<DataObject> results; private String ticker; private String status; // 无参构造(建议保留) public Transcript() {} // Getter/Setter方法,供外部访问私有字段 public List<DataObject> getResults() { return results; } public void setResults(List<DataObject> results) { this.results = results; } public String getTicker() { return ticker; } public void setTicker(String ticker) { this.ticker = ticker; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } }
3. 主类代码调整
原有主类代码可直接使用,Gson会自动完成解析:
Gson gson = new Gson(); // 假设getResponse.body()为JSON字符串或Reader类型 Transcript transcript = gson.fromJson(getResponse.body(), Transcript.class); // 验证解析结果 System.out.println("Status: " + transcript.getStatus()); System.out.println("Ticker: " + transcript.getTicker()); System.out.println("Results:"); for (DataObject obj : transcript.getResults()) { System.out.println(obj); }
4. 私有字段的访问处理
若使用私有字段,可通过两种方式让Gson正常赋值:
- 保留上述Getter/Setter方法,Gson会自动调用Setter赋值
- 配置Gson并添加注解,示例如下:
// 主类中配置Gson Gson gson = new GsonBuilder() .setFieldNamingPolicy(FieldNamingPolicy.IDENTITY) .excludeFieldsWithoutExposeAnnotation() .create();
同时在实体类私有字段上添加@Expose注解:
import com.google.gson.annotations.Expose; public class Transcript { @Expose private List<DataObject> results; @Expose private String ticker; @Expose private String status; // Getter/Setter方法... }
内容的提问来源于stack exchange,提问作者Piemanray314
相关产品推荐
相关产品推荐

