<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 495,comments - 227,trackbacks - 0

    http://simpleframework.net/blog/v/20118.html


    在Java平臺(StAX, JAXB等)XML處理質量和多樣化的激勵下,Jackson為多功能的Java JSON處理包其目標為集快捷、正確、輕量和符合人體工程學與一體。

    本文將給出Jackson的功能概覽。

    JSON的三種處理方式 
    Jackson提供了三種可選的JSON處理方法(一種方式及其兩個變型):

    • 流式 API(也稱為"增量分析/生成") 讀取和寫入 JSON 內容作為離散事件。

    • 樹模型 :提供一個 JSON 文檔可變內存樹的表示形式。

      • org.codehaus.jackson.map.ObjectMapper 生成樹 ;樹組成 JsonNode 節點集。

      • 樹模型類似于 XML DOM。
    • 數據綁定: JSON和POJO相互轉換,基于屬性訪問器規約或注解。

      • 兩種變體簡單完整 的數據綁定:

      • 簡單數據綁定: 是指從Java Map、List、String、Numbers、Boolean和空值進行轉換

      • 完整數據綁定 :是指從任何 Java bean 類型 (及上文所述的"簡單"類型) 進行轉換

      • org.codehaus.jackson.map.ObjectMapper 對兩個變種,進行編組(marshalling )處理 (寫入 JSON) 和反編組(unmarshalling ,讀 JSON)。

      • JAXB激勵下的基于注釋的 (代碼優先)變種。

    從使用的角度來看,總結這些3 種方法的用法如下:

    • 流 API: 性能最佳的方式 (最低開銷、 速度最快的讀/寫; 其它二者基于它實現)。

    • 數據綁定 :使用最方便的方式。

    • 樹模型: 最靈活的方式。

    鑒于這些特性,讓我們考慮以相反的順序,以Java開發人員最自然和方便的方法開始使用: 杰Jackson數據綁定 API

    Jackson的 org.codehaus.jackson.map.ObjectMapper "只是"將JSON 數據映射為POJO 對象 。例如,給定 JSON 數據:

    {
      "name" : { "first" : "Joe", "last" : "Sixpack" },
      "gender" : "MALE",
      "verified" : false,
      "userImage" : "Rm9vYmFyIQ=="
    }

    用兩行代碼把它變成一個用戶實例:

    1 ObjectMapper mapper = new ObjectMapper(); // can reuse, share globally
    2 User user = mapper.readValue(new File("user.json"), User.class);

    用戶類大致如下(源自另一博客):

    1 public class User {
    2 public enum Gender { MALE, FEMALE };
    3
    4 public static class Name {
    5 private String _first, _last;
    6
    7 public String getFirst() { return _first; }
    8 public String getLast() { return _last; }
    9
    10 public void setFirst(String s) { _first = s; }
    11 public void setLast(String s) { _last = s; }
    12 }
    13
    14 private Gender _gender;
    15 private Name _name;
    16 private boolean _isVerified;
    17 private byte[] _userImage;
    18
    19 public Name getName() { return _name; }
    20 public boolean isVerified() { return _isVerified; }
    21 public Gender getGender() { return _gender; }
    22 public byte[] getUserImage() { return _userImage; }
    23
    24 public void setName(Name n) { _name = n; }
    25 public void setVerified(boolean b) { _isVerified = b; }
    26 public void setGender(Gender g) { _gender = g; }
    27 public void setUserImage(byte[] b) { _userImage = b; }
    28 }

    編組為JSON同樣簡單:

    mapper.writeValue(new File("user-modified.json"), user);

     對于更復雜的數據綁定 (例如,反編排格式日期到 java.util.Date),Jackson提供注解來自定義編排和反編排的處理過程。

    簡單的數據綁定示例
    如果你沒有 (或不想創建)從 JSON到 Java 的相互轉化類,簡單數據綁定可能是更好的方法。它用相同方式實現完整的數據綁定,除非形式化綁定類型只指定為 Object.class (或 Map.class, List.class,即使需要更多的類型定義)。因此早期綁定JSON的用戶數據可能如此實現:

    Map<String,Object> userData = mapper.readValue(new File("user.json"), Map.class);

     userData 像一個的顯式結構:

       1 Map<String,Object> userData = new HashMap<String,Object>();    2 Map<String,String> nameStruct = new HashMap<String,String>();    3 nameStruct.put("first", "Joe");    4 nameStruct.put("last", "Sixpack");    5 userData.put("name", nameStruct);    6 userData.put("gender", "MALE");    7 userData.put("verified", Boolean.FALSE);    8 userData.put("userImage", "Rm9vYmFyIQ=="); 
    這顯然是雙向的: 如果利用諸如Map 的結構構建(或從 JSON綁定及修改),也可以如前法實現:
    Map<String,Object> userData = mapper.readValue(new File("user.json"), Map.class);
    將如何工作呢? 只定義了Map.class,未定義一般的Key/valie類型,但ObjectMapper 卻知曉與Map(及List、數組、wrapper類型 )之間如何相互轉換,僅是如此即可。如果它可以正確地映射到您所提供的類型,它將被映射。
     
    Jackson將使用簡單數據綁定的具體Java 類型包括:
    JSON Type Java Type
    object LinkedHashMap<String,Object>
    array ArrayList<Object>
    string String
    number(no fraction) Integer, Long or BigInteger (smallest applicable)
    number (fraction) BigDecimal
    true|false boolean
    null null

    泛型的數據綁定

    除綁定到POJO和簡單類型外,還有一個額外的變型:綁定到泛型(類型)容器。此時,由于所謂的類型擦除(Java采用向后兼容的方式實現泛型),需要進行特殊處理,以防止使用類似 Collection<String>.class(不被編譯)。

    所以,熱想綁定數據島Map<String,User>,方式如下:

    Map<String,User> result = mapper.readValue(src, new TypeReference<Map<String,User>>() { });

    其中TypeReference只需傳入泛型類型即可(此時需要匿名內部類):重要部分為<Map<String,User>>,定義要綁定的數據類型。

    若不如此(僅定義Map.class),其調用等價于綁定到 Map<?,?>(亦即 “untyped” Map),如前所述。

    更新:1.3版的Jackson允許利用TypeFactory實現構造類型。

    樹模式示例

    另一種從JSON獲取對象方式是構造“樹”,類似于XML的DOM樹。Jackson構造樹的方法利用JsonNode基類,其中包含公開的通常所需的讀取訪問方法,實際所用的節點類型為其子類;但子類型僅在修改樹時需要。

    JSON樹可通過流式API或ObjectMapper方式讀、寫。

    利用 ObjectMapper,方法如下:

      1 ObjectMapper m = new ObjectMapper();
       2 // can either use mapper.readTree(JsonParser), or bind to JsonNode
       3 JsonNode rootNode = m.readValue(new File("user.json"), JsonNode.class);
       4 // ensure that "last name" isn't "Xmler"; if is, change to "Jsoner"
       5 JsonNode nameNode = rootNode.path("name");
       6 String lastName = nameNode.path("last").getTextValue().
       7 if ("xmler".equalsIgnoreCase(lastName)) {
       8   ((ObjectNode)nameNode).put("last", "Jsoner");
       9 }
      10 // and write it out:
      11 m.writeValue(new File("user-modified.json"), rootNode);

     或你想馬上構造一棵樹,方法如下:

      1 TreeMapper treeMapper = new TreeMapper();
       2 ObjectNode userOb = treeMapper.objectNode();
       3 Object nameOb = userRoot.putObject("name");
       4 nameOb.put("first", "Joe");
       5 nameOb.put("last", "Sixpack");
       6 userOb.put("gender", User.Gender.MALE.toString());
       7 userOb.put("verified", false);
       8 byte[] imageData = getImageData(); // or wherever it comes from
       9 userOb.put("userImage", imageData);

     (注意: Jackson 1.2可直接使用ObjectMapper:通過ObjectMapper.createObjectNode()創建userOb -- 上例工作于Jackson 1.0 和 1.1)。

    流式 API 示例
     
    最后,還有第三種方式: 渦輪增壓、 高性能的方法稱為流 API (或增量模式,因為內容是增量讀取和寫入的)。

    只是為了好玩,讓我們實現使用"原生"Stream  API 的寫入功能 (相當于前面示例): WriteJSON.java

       1 JsonFactory f = new JsonFactory();
       2 JsonGenerator g = f.createJsonGenerator(new File("user.json"));
       3
       4 g.writeStartObject();
       5 g.writeObjectFieldStart("name");
       6 g.writeStringField("first", "Joe");
       7 g.writeStringField("last", "Sixpack");
       8 g.writeEndObject(); // for field 'name'
       9 g.writeStringField("gender", Gender.MALE);
      10 g.writeBooleanField("verified", false);
      11 g.writeFieldName("userImage"); // no 'writeBinaryField' (yet?)
      12 byte[] binaryData = ...;
      13 g.writeBinary(binaryData);
      14 g.writeEndObject();
      15 g.close(); // 重要:強制寫入輸出,并關閉輸出流!

     非常不錯 (尤其是相對寫入所需的工作量,亦即等效的 XML 內容),但肯定比基本對象映射更辛苦。

    另一方面,必須完全控制每一個細節。開銷很小: 這仍然快于使用 ObjectMapper;并非快很多 ,但還是要快些(一般快或許 20-30%)。也許最重要的是,以流方式輸出: 除一些緩沖外,所有內容都將馬上輸出。這意味著該方式內存使用量也是最小的。

    然后如何解析呢?代碼可能看起來類似:

       1 JsonFactory f = new JsonFactory();
       2 JsonParser jp = f.createJsonParser(new File("user.json"));
       3 User user = new User();
       4 jp.nextToken(); // will return JsonToken.START_OBJECT (verify?)
       5 while (jp.nextToken() != JsonToken.END_OBJECT) {
       6   String fieldname = jp.getCurrentName();
       7   jp.nextToken(); // move to value, or START_OBJECT/START_ARRAY
       8   if ("name".equals(fieldname)) { // contains an object
       9     Name name = new Name();
      10     while (jp.nextToken() != JsonToken.END_OBJECT) {
      11       String namefield = jp.getCurrentName();
      12       jp.nextToken(); // move to value
      13       if ("first".equals(namefield)) {
      14         name.setFirst(jp.getText());
      15       } else if ("last".equals(namefield)) {
      16         name.setLast(jp.getText());
      17       } else {
      18         throw new IllegalStateException("Unrecognized field '"+fieldname+"'!");
      19       }
      20     }
      21     user.setName(name);
      22   } else if ("gender".equals(fieldname)) {
      23     user.setGender(Gender.valueOf(jp.getText()));
      24   } else if ("verified".equals(fieldname)) {
      25     user.setVerified(jp.getCurrentToken() == JsonToken.VALUE_TRUE);
      26   } else if ("userImage".equals(fieldname)) {
      27     user.setUserImage(jp.getBinaryValue());
      28   } else {
      29     throw new IllegalStateException("Unrecognized field '"+fieldname+"'!");
      30   }
      31 }
      32 jp.close(); // ensure resources get cleaned up timely and properly

     這是不是您將更多使用的數據綁定方法。

    最后提醒的一個竅門: 可可能通過JsonParser 和 JsonGeneratorit 直接實現數據綁定和樹模式。請參閱如下方法:

    • JsonParser.readValueAs()
    • JsonParser.readValueAsTree()
    • JsonGenerator.writeObject()
    • JsonGenerator.writeTree()

    將實現你期望的結果。
    切記,確保所用的 org.codehaus.jackson.map.MappingJsonFactory是"適用數據綁定“的解析器和生成器實例(而非基本的org.codehaus.jackson.JsonFactory)。

    posted on 2012-09-06 16:47 SIMONE 閱讀(17401) 評論(2)  編輯  收藏 所屬分類: JAVA

    FeedBack:
    # re: Java JSON(二)5分鐘學會Jackson
    2013-12-27 11:50 | 柳qing·
    User user = mapper.readValue(new File("user.json"), User.class);

    讀文件老是錯誤,怎么回事呢?  回復  更多評論
      
    # JSON
    2013-12-28 09:58 | JSON
    JSON是個好東西. 優點數據傳輸體積小,跨平臺跨語言都可以使用.

    另外推薦一個JSON工具 http://www.sojson.com

    無廣告加載快, 很適合新手和經常用JSON的同學們  回復  更多評論
      
    主站蜘蛛池模板: 18禁亚洲深夜福利人口| 久久久久亚洲精品日久生情 | 在线亚洲午夜理论AV大片| 国产精品亚洲精品日韩动图| 免费高清av一区二区三区| 亚洲欧洲日韩极速播放| 妞干网免费视频观看| 亚洲人成网站在线播放2019 | 最近2018中文字幕免费视频 | 亚洲欧洲国产精品你懂的| 欧洲人成在线免费| 亚洲国产美国国产综合一区二区| 久久久高清日本道免费观看| 亚洲成av人影院| 最近中文字幕大全中文字幕免费| 亚洲毛片无码专区亚洲乱| 毛片在线免费视频| 亚洲AV无码片一区二区三区| 亚洲国产精品无码久久久久久曰| 一个人免费观看日本www视频| 亚洲色欲一区二区三区在线观看| 久久精品一区二区免费看| 亚洲国产美女福利直播秀一区二区| 成人黄软件网18免费下载成人黄18免费视频 | 一级毛片免费不卡直观看| 亚洲乱码国产乱码精品精| 免费A级毛片在线播放| 亚洲人成小说网站色| 亚洲日本在线观看视频| 98精品全国免费观看视频| 亚洲欧美日韩自偷自拍| 精品国产日韩亚洲一区| 在线永久看片免费的视频| 国产精品亚洲专区一区| 久久精品国产精品亚洲艾| 免费羞羞视频网站| 国产婷婷成人久久Av免费高清| 亚洲日本在线观看网址| 亚洲欧洲一区二区三区| 国产成人免费高清激情明星| 免费播放国产性色生活片|