2014-04-04 212 views
0

的Json API解析煩惱我遇到類似什麼人有過在Java JSON解析過去的幾個問題。這是我第一次嘗試這樣的事情,所以任何幫助/提示都非常有用。與Java

我想從這個站點的數據來分析:https://api.bitcoinaverage.com/exchanges/USD

我試圖與這兩個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:

public class Rates { 
    private Number ask; 
    private Number bid; 
    private Number last; 

    public Number getAsk(){ 
     return this.ask; 
    } 
    public void setAsk(Number ask){ 
     this.ask = ask; 
    } 
    public Number getBid(){ 
     return this.bid; 
    } 
    public void setBid(Number bid){ 
     this.bid = bid; 
    } 
    public Number getLast(){ 
     return this.last; 
    } 
    public void setLast(Number last){ 
     this.last = last; 
    } 
} 

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」的屬性。

這是第一次我在這裏張貼的東西,所以我希望我遵循正確的指導方針。

我還打算通過這個上到Android,一旦我得到的下跌,解析JSON更好。謝謝您的幫助!它將不勝感激。

+0

的_Info_類型不匹配頂層JSON對象的屬性。你需要一個帶有bitfinex屬性的對象來獲取這些數據。 – McDowell

回答

1

我會跟你說實話,這是一個非常蹩腳的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對象(共享一種格式)和一個名稱爲timestamp的JSON名稱值對。

常見的JSON對象有double類型的兩個領域(這是什麼類型的字段應該是,不Number

"volume_btc": 11.73, 
"volume_percent": 0.02 

,類型String

"display_URL": "https://anxbtc.com/", 
"display_name": "ANXBTC", 
"source": "bitcoincharts", 

三個領域,一個是它包含三個雙打

"rates": { 
     "ask": 454.26, 
     "bid": 444.46, 
     "last": 443.78 
} 
一個JSON對象

這裏的實際問題是,我假設根JSON對象中的JSON對象的名稱可能會更改,或者可能會添加新的名稱。這不適合POJO。相反,你想使用Map<String, Info>,但Gson默認無法映射到該值。它不適合這種反序列化。你必須提供你自己的TypeAdapter

相反,我會建議你使用傑克遜。

如果我們把所有的一起,我們得到類似

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; 
    } 
} 

隨着諸如

String json = readUrl("https://api.bitcoinaverage.com/exchanges/USD"); 

ObjectMapper mapper = new ObjectMapper(); 
ApiResponse response = mapper.readValue(json, ApiResponse.class); 
System.out.println(response); 

通過適當toString()方法(我用的Eclipse自動生成的)反序列化的代碼,你會得到像

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] 

作爲輸出。

+0

謝謝!這幫了一大筆錢。我能夠更多地從事這方面的工作。 – AlwaysLearning

1

api響應包含許多對象,但似乎您試圖將它們作爲單個Info對象來閱讀。
您可能會嘗試將響應讀取爲Map<String, Info>,並迭代條目。

Map<String, Info> hashMap = gson.fromJson(body, HashMap.class); 
for (Map.Entry entry : hashMap.entrySet()) { 
    // your code 
} 
+0

然而,它們並不都是Info的對象。 –