Java的Json API解析问题
我遇到了一些类似于其他人过去在Java中使用Json解析时遇到的问题。这是我第一次尝试这样的东西,所以任何帮助/提示都非常有用 我正在尝试解析来自此站点的数据: 我用Json和Gson尝试了很多方法。并试图在这里寻求帮助,但无济于事 以下是设置的类(这些类是自动生成的): Info.java:Java的Json API解析问题,java,json,Java,Json,我遇到了一些类似于其他人过去在Java中使用Json解析时遇到的问题。这是我第一次尝试这样的东西,所以任何帮助/提示都非常有用 我正在尝试解析来自此站点的数据: 我用Json和Gson尝试了很多方法。并试图在这里寻求帮助,但无济于事 以下是设置的类(这些类是自动生成的): Info.java: public class Info{ private String display_URL; private String display_name; private Ra
public class Info{
private String display_URL;
private String display_name;
private Rates[] rates;
private String source;
private Number volume_btc;
private Number volume_percent;
public String getDisplay_URL(){
return this.display_URL;
}
public void setDisplay_URL(String display_URL){
this.display_URL = display_URL;
}
public String getDisplay_name(){
return this.display_name;
}
public void setDisplay_name(String display_name){
this.display_name = display_name;
}
public Rates[] getRates(){
return this.rates;
}
public void setRates(Rates[] rates){
this.rates = rates;
}
public String getSource(){
return this.source;
}
public void setSource(String source){
this.source = source;
}
public Number getVolume_btc(){
return this.volume_btc;
}
public void setVolume_btc(Number volume_btc){
this.volume_btc = volume_btc;
}
public Number getVolume_percent(){
return this.volume_percent;
}
public void setVolume_percent(Number volume_percent){
this.volume_percent = volume_percent;
}
}
Rates.java:
MainClass.java:
public class MainClass {
public static void main(String[] args) throws Exception {
Gson gson = new Gson();
String json = readUrl("https://api.bitcoinaverage.com/exchanges/USD");
Info page = gson.fromJson(json, Info.class);
System.out.println(page.getDisplay_name());
}
private static String readUrl(String urlString) throws Exception {
BufferedReader reader = null;
try {
URL url = new URL(urlString);
reader = new BufferedReader(new InputStreamReader(url.openStream()));
StringBuffer buffer = new StringBuffer();
int read;
char[] chars = new char[1024];
while ((read = reader.read(chars)) != -1)
buffer.append(chars, 0, read);
return buffer.toString();
} finally {
if (reader != null)
reader.close();
}
}
}
当我尝试调用getter时,返回null。
如何正确解析数据,然后能够调用我想要的对象的属性?例如,如果我想要“anx_hk”或“bitfinex”中的属性
这是我第一次在这里发布一些东西,所以我希望我遵循正确的指导原则
我还计划在获得更好的Json解析能力后,将其传递给Android。谢谢你的帮助!非常感谢 老实说,这是一个相当蹩脚的API响应。给你
{
"anx_hk": {
"display_URL": "https://anxbtc.com/",
"display_name": "ANXBTC",
"rates": {
"ask": 454.26,
"bid": 444.46,
"last": 443.78
},
"source": "bitcoincharts",
"volume_btc": 11.73,
"volume_percent": 0.02
},
...,
"timestamp": "Fri, 04 Apr 2014 04:30:26 -0000",
...
}
这里没有JSON数组,因此可以去掉所有数组类型。此响应是一个JSON对象,它包含一组JSON对象(共享一种格式)和一个JSON名称-值对,其中名称为timestamp
常见的JSON对象有两个类型为double
(这是字段的类型,而不是Number
)
,三个类型为String
"display_URL": "https://anxbtc.com/",
"display_name": "ANXBTC",
"source": "bitcoincharts",
还有一个是JSON对象,它包含三个以上的双精度
"rates": {
"ask": 454.26,
"bid": 444.46,
"last": 443.78
}
这里的实际问题是,我假设根JSON对象中的JSON对象具有可能更改或添加新名称的名称。这不适合POJO。相反,您希望使用映射
,但默认情况下Gson无法映射到该映射。它不太适合这种反序列化。您必须提供自己的TypeAdapter
相反,我建议你使用Jackson
如果我们把这些放在一起,我们会得到
class ApiResponse {
private Map<String, Info> page = new HashMap<>();
private Date timestamp;
public Map<String, Info> getPage() {
return page;
}
@JsonAnySetter
public void setPage(String name, Info value) {
page.put(name, value);
}
public Date getTimestamp() {
return timestamp;
}
public void setTimestamp(Date timestamp) {
this.timestamp = timestamp;
}
}
class Info {
private String display_URL;
private String display_name;
private Rates rates;
private String source;
private Double volume_btc;
private Double volume_percent;
public String getDisplay_URL() {
return this.display_URL;
}
public void setDisplay_URL(String display_URL) {
this.display_URL = display_URL;
}
public String getDisplay_name() {
return this.display_name;
}
public void setDisplay_name(String display_name) {
this.display_name = display_name;
}
public Rates getRates() {
return this.rates;
}
public void setRates(Rates rates) {
this.rates = rates;
}
public String getSource() {
return this.source;
}
public void setSource(String source) {
this.source = source;
}
public Double getVolume_btc() {
return this.volume_btc;
}
public void setVolume_btc(Double volume_btc) {
this.volume_btc = volume_btc;
}
public Double getVolume_percent() {
return this.volume_percent;
}
public void setVolume_percent(Double volume_percent) {
this.volume_percent = volume_percent;
}
}
class Rates {
private Double ask;
private Double bid;
private Double last;
public Number getAsk() {
return this.ask;
}
public void setAsk(Double ask) {
this.ask = ask;
}
public Double getBid() {
return this.bid;
}
public void setBid(Double bid) {
this.bid = bid;
}
public Double getLast() {
return this.last;
}
public void setLast(Double last) {
this.last = last;
}
}
ApiResponse [pages={bitkonan=Info [display_URL=https://bitkonan.com/, display_name=BitKonan, rates=Rates [ask=475.0, bid=438.01, last=437.0], source=api, volume_btc=7.24, volume_percent=0.01], vaultofsatoshi=Info [display_URL=https://vaultofsatoshi.com, display_name=Vault of Satoshi, rates=Rates [ask=460.0, bid=460.0, last=460.0], source=api, volume_btc=11.46, volume_percent=0.02], bitstamp=Info [display_URL=https://bitstamp.net/, display_name=Bitstamp, rates=Rates [ask=439.16, bid=436.34, last=436.34], source=api, volume_btc=22186.29, volume_percent=35.19], ...}, timestamp=Fri Apr 04 01:02:43 EDT 2014]
使用适当的toString()
方法(我的方法是用Eclipse自动生成的),您会得到如下结果
class ApiResponse {
private Map<String, Info> page = new HashMap<>();
private Date timestamp;
public Map<String, Info> getPage() {
return page;
}
@JsonAnySetter
public void setPage(String name, Info value) {
page.put(name, value);
}
public Date getTimestamp() {
return timestamp;
}
public void setTimestamp(Date timestamp) {
this.timestamp = timestamp;
}
}
class Info {
private String display_URL;
private String display_name;
private Rates rates;
private String source;
private Double volume_btc;
private Double volume_percent;
public String getDisplay_URL() {
return this.display_URL;
}
public void setDisplay_URL(String display_URL) {
this.display_URL = display_URL;
}
public String getDisplay_name() {
return this.display_name;
}
public void setDisplay_name(String display_name) {
this.display_name = display_name;
}
public Rates getRates() {
return this.rates;
}
public void setRates(Rates rates) {
this.rates = rates;
}
public String getSource() {
return this.source;
}
public void setSource(String source) {
this.source = source;
}
public Double getVolume_btc() {
return this.volume_btc;
}
public void setVolume_btc(Double volume_btc) {
this.volume_btc = volume_btc;
}
public Double getVolume_percent() {
return this.volume_percent;
}
public void setVolume_percent(Double volume_percent) {
this.volume_percent = volume_percent;
}
}
class Rates {
private Double ask;
private Double bid;
private Double last;
public Number getAsk() {
return this.ask;
}
public void setAsk(Double ask) {
this.ask = ask;
}
public Double getBid() {
return this.bid;
}
public void setBid(Double bid) {
this.bid = bid;
}
public Double getLast() {
return this.last;
}
public void setLast(Double last) {
this.last = last;
}
}
ApiResponse [pages={bitkonan=Info [display_URL=https://bitkonan.com/, display_name=BitKonan, rates=Rates [ask=475.0, bid=438.01, last=437.0], source=api, volume_btc=7.24, volume_percent=0.01], vaultofsatoshi=Info [display_URL=https://vaultofsatoshi.com, display_name=Vault of Satoshi, rates=Rates [ask=460.0, bid=460.0, last=460.0], source=api, volume_btc=11.46, volume_percent=0.02], bitstamp=Info [display_URL=https://bitstamp.net/, display_name=Bitstamp, rates=Rates [ask=439.16, bid=436.34, last=436.34], source=api, volume_btc=22186.29, volume_percent=35.19], ...}, timestamp=Fri Apr 04 01:02:43 EDT 2014]
作为输出。api响应包含许多对象,但您似乎试图将它们作为单个信息对象来读取。
您可以尝试将响应读取为
映射
,然后迭代条目
Map<String, Info> hashMap = gson.fromJson(body, HashMap.class);
for (Map.Entry entry : hashMap.entrySet()) {
// your code
}
Map hashMap=gson.fromJson(body,hashMap.class);
for(Map.Entry:hashMap.entrySet()){
//你的代码
}
信息类型与顶级JSON对象的属性不匹配。您需要一个具有bitfinex属性的对象来获取该数据。但是,它们并不都是Info
对象。谢谢!这帮了大忙。我能从中得到更多的东西。
Map<String, Info> hashMap = gson.fromJson(body, HashMap.class);
for (Map.Entry entry : hashMap.entrySet()) {
// your code
}