Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java的Json API解析问题_Java_Json - Fatal编程技术网

Java的Json API解析问题

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

我遇到了一些类似于其他人过去在Java中使用Json解析时遇到的问题。这是我第一次尝试这样的东西,所以任何帮助/提示都非常有用

我正在尝试解析来自此站点的数据:

我用Json和Gson尝试了很多方法。并试图在这里寻求帮助,但无济于事

以下是设置的类(这些类是自动生成的):

Info.java:

    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
}