2015-05-30 33 views
1

我從來沒有試圖解析過JSON。我有一個JSON格式的一些書是這樣的:如何解析Java中的對象的JSON數組

{ 
"Search": { 
    "Books": [ 
     { 
      "isbn": "1849830347", 
      "title": "American Assassin", 
      "author": "Vince Flynn", 
      "price": 7.99 
     }, 
     { 
      "isbn": "0857208683", 
      "title": Kill Shot", 
      "author": "Vince Flynn", 
      "price": 5.99 
     }, 
     ... 
    } 
} 

我想要的是對其進行解析,並用填充圖書對象的列表結束。我曾與傑克遜和Google的GSON一起玩過。我終於得到了這個工作,但我並不滿意。這只是代碼的作用,我希望我的解決方案是未來再次使用JSON時的良好代碼 - 我想這是低效的,因爲我首先將它轉換爲樹並解析它。任何人都可以改進?

List<Book> books = new ArrayList<Book>(); 
JsonFactory f = new JsonFactory(); 
JsonParser jp = f.createJsonParser(json); 
jp.setCodec(new ObjectMapper()); 
JsonNode node = jp.readValueAsTree(); 

JsonNode books = node.findValue("Books"); 

Iterator<JsonNode> it = books.getElements(); 
while(it.hasNext()){ 
    JsonNode temp = it.next(); 
    Book book = new Book(); 
    book.setIsbn(temp.findValue("isbn").asText()); 
    book.setTitle(temp.findValue("title").asText()); 
    book.setAuthor(temp.findValue("author").asText()); 
    book.setPrice(temp.findValue("price").asDouble()); 
    books.add(book); 
} 

唯一的原因,我有setCodec線是因爲沒有它,我得到與消息的IllegalStateException:沒有ObjectCodec解析器定義,無法反序列化JSON到JsonNode樹。

Jackson API,我曾嘗試使用Streaming API方法。但是我只需要調用jp.nextToken()約10次就可以得到第一個isbn值,而且看起來非常混亂。雖然API確實說了20%/ 30%的速度。

欣賞對此的任何反饋。

+0

可能重複:http://stackoverflow.com/questions/6349421/how-使用傑克遜到反串行化的對象數組 –

回答

0

可用一些JSON庫更加或者不那麼麻煩。在我看來,遍歷樹是使用外部庫時你不應該關心的事情之一。在這種情況下,你甚至可以自己寫。

但是前段時間我找到了一個很好的庫,它可以爲你做所有這些工作,叫做json-io。 這個庫的缺點是它不適用於Android。 (我在Android上遇到了OutOfMemory異常。)

0

Jackson提供了三個解析級別:流API是基礎層,解析JSON到樹節點或您自己的類被提供。儘管直接使用流媒體API可能效率最高,但您需要花費大量人力。

實際上你所需要的大部分似乎都在1-minute tutorial之內,不需要向前跳!

傑克遜可以直接創建/填充自己的Book對象,而不是解析到JsonNode。既然你已經有bean風格的setter,這應該是一個簡單的插件。

(順便說一句典型的用法是從它創建一個ObjectMapper通常initially--作爲singleton--創造JsonFactory,ObjectReader等,而不是倒過來)

所以你可以讀出一個Book對象所以:

Book book = mapper.readValue("{\"isbn\":\"1849830347\"}", Book.class); 

你可以建立某種形式的包裝對象來表示下的 「搜索」 鍵的對象:

/*static*/ class SearchResult { 
    @JsonProperty("Books") 
    public List<Book> books; 
} 
SearchResult result = mapper.readValue("{\"Books\":[{\"isbn\":\"...\"}]}", SearchResult.class); 
List<Book> books = result.books; 

@JsonProperty需要指定大寫的「Books」字段名稱,而不是默認值。作爲一個簡潔的公共領域顯示,一個私人領域與吸氣和二傳手也可以)

然後你可以添加另一層對象來表示整個消息,或添加一個@JsonRootName註釋告訴傑克遜做一個額外的水平的展開,當信息搜索結果是「根」類型:

@JsonRootName(value="Search") 
class SearchResult { ... } 

很多,你能避免使用JsonNode,JsonFactory等與傑克遜直接的時間。如果您只爲屬性名稱等註釋類,那麼對於分析格式,您幾乎沒有辦法使用對稱類。

0

我已經在許多項目中使用過傑克遜,並將在未來毫不猶豫地再次使用它。

在大多數情況下,我喜歡開發模擬JSON消息的java POJO。所以你的情況,你需要一本書POJO到您的JSON的這種內部

{ 
    "isbn": "1849830347", 
    "title": "American Assassin", 
    "author": "Vince Flynn", 
    "price": 7.99 
} 

匹配POJO將這個

public class BookVO { 

    private final String isbn; 
    private final String title; 
    private final String author; 
    private final double price; 

    @JsonCreator 
    public BookVO(@JsonProperty("isbn") final String isbn, @JsonProperty("title") final String title, @JsonProperty("author") final String author, @JsonProperty("price") final double price) { 
     super(); 
     this.isbn = isbn; 
     this.title = title; 
     this.author = author; 
     this.price = price; 
    } 

    public String getIsbn() { 
     return isbn; 
    } 

    public String getTitle() { 
     return title; 
    } 

    public String getAuthor() { 
     return author; 
    } 

    public double getPrice() { 
     return price; 
    } 

} 

以上書中的父POJO模型是本

public class BookSearchVO { 

    private final BookVO[] books; 

    @JsonCreator 
    public BookSearchVO(@JsonProperty("Books") final BookVO[] books) { 
     super(); 
     this.books = books; 
    } 

    public BookVO[] getBooks() { 
     return books; 
    } 

} 

大父POJO是這樣

public class SearchVO { 

    private final BookSearchVO search; 

    @JsonCreator 
    public SearchVO(@JsonProperty("Search") final BookSearchVO search) { 
     super(); 
     this.search = search; 
    } 

    public BookSearchVO getSearch() { 
     return search; 
    } 

} 

的將JSON轉換成Java對象僅僅做到這一點

final ObjectMapper mapperBook = new ObjectMapper(); 
final SearchVO results = mapperBook.readValue(new File("books.json"), SearchVO.class); 

books.json的內容是

{ 
    "Search":{ 
     "Books":[ 
     { 
      "isbn":"1849830347", 
      "title":"American Assassin", 
      "author":"Vince Flynn", 
      "price":7.99 
     }, 
     { 
      "isbn":"0857208683", 
      "title":"Kill Shot", 
      "author":"Vince Flynn", 
      "price":5.99 
     } 
     ] 
    } 
}