zoukankan      html  css  js  c++  java
  • 一个现代化的JSON库Moshi针对Android和Java

    Moshi

    是一个现代化的JSON库针对Android和Java。它可以很容易地解析JSON成Java对象:

    
    
    String json = ...;
    
    Moshi moshi = new Moshi.Builder().build();
    JsonAdapter<BlackjackHand> jsonAdapter = moshi.adapter(BlackjackHand.class);
    
    BlackjackHand blackjackHand = jsonAdapter.fromJson(json);
    System.out.println(blackjackHand);

    它可以很容易地Java对象序列为JSON:

    
    
    BlackjackHand blackjackHand = new BlackjackHand(
        new Card('6', SPADES),
        Arrays.asList(new Card('4', CLUBS), new Card('A', HEARTS)));
    
    Moshi moshi = new Moshi.Builder().build();
    JsonAdapter<BlackjackHand> jsonAdapter = moshi.adapter(BlackjackHand.class);
    
    String json = jsonAdapter.toJson(blackjackHand);
    System.out.println(json);

    内置型适配器

    莫西已经内置了支持读取和写入Java的核心数据类型:

    • 原语(整型,浮点,焦炭......)及其同行盒装(整数,浮点数,字符...)。
    • 数组,集合,列表,集合和地图
    • 字符串
    • 枚举

    它通过写出来场逐场支持你的模型类。在上面的莫希例子使用这些类:

    
    
    class BlackjackHand {
      public final Card hidden_card;
      public final List<Card> visible_cards;
      ...
    }
    
    class Card {
      public final char rank;
      public final Suit suit;
      ...
    }
    
    enum Suit {
      CLUBS, DIAMONDS, HEARTS, SPADES;
    }

    读写此JSON:

    
    
    {
      "hidden_card": {
        "rank": "6",
        "suit": "SPADES"
      },
      "visible_cards": [
        {
          "rank": "4",
          "suit": "CLUBS"
        },
        {
          "rank": "A",
          "suit": "HEARTS"
        }
      ]
    }

    Javadoc中编目完整的莫西API,我们将在下面探讨。

    自定义类型的适配器

    随着磨石,这是特别容易定制值的转换方式,并从JSON。A型适配器是有注释的方法,任何类@ToJson@FromJson

    例如,磨石的一张扑克牌的默认编码为详细:JSON的定义在不同领域的点数和花色:{“等级”:“A”,“套装”:“心”}随着类型的适配器,我们可以改变编码的东西更紧凑:“4H”为心中的四,“JD”为钻石插孔:

    
    
    class CardAdapter {
      @ToJson String toJson(Card card) {
        return card.rank + card.suit.name().substring(0, 1);
      }
    
      @FromJson Card fromJson(String card) {
        if (card.length() != 2) throw new JsonDataException("Unknown card: " + card);
    
        char rank = card.charAt(0);
        switch (card.charAt(1)) {
          case 'C': return new Card(rank, Suit.CLUBS);
          case 'D': return new Card(rank, Suit.DIAMONDS);
          case 'H': return new Card(rank, Suit.HEARTS);
          case 'S': return new Card(rank, Suit.SPADES);
          default: throw new JsonDataException("unknown suit: " + card);
        }
      }
    }

    注册与该类型的适配器Moshi.Builder,我们是好去。

    
    
    Moshi moshi = new Moshi.Builder()
        .add(new CardAdapter())
        .build();

    Voila:

    {
      "hidden_card": "6S",
      "visible_cards": [
        "4C",
        "AH"
      ]
    }

    另一个安卓源码例子

    需要注意的是带注释方法@FromJson并不需要采取一个字符串作为参数。相反,它可以采取任何类型的输入和磨石将首先解析JSON到该类型的对象,然后使用@FromJson方法以产生所需的最终值。相反,带注释的方法@ToJson没有产生一个字符串。

    假设,例如,我们必须分析,其中一个事件的日期和时间被表示为两个独立的字符串一个JSON。

    
    
    {
      "title": "Blackjack tournament",
      "begin_date": "20151010",
      "begin_time": "17:04"
    }

    我们想这两个字段合并为一个串,以方便的时间在稍后分析。同时,我们希望有首字母大写的所有变量名。因此,事件 我们要莫希产生这样的类:

    
    
    class Event {
      String title;
      String beginDateAndTime;
    }

    不用手动解析每行的JSON行(我们也可以做到),我们可以有莫希自动完成改造。我们简单地定义另一个类EventJson直接对应于JSON结构:

    
    
    class EventJson {
      String title;
      String begin_date;
      String begin_time;
    }

    并用适当的另一个类@FromJson@ToJson被告知莫希如何将一个转换方法EventJson一个事件和背部。现在,每当我们要求莫希分析一个JSON到一个事件,将首先将其解析到一个EventJson作为一个中间步骤。相反,序列化一个事件莫希将首先创建一个EventJson对象,然后序列化对象如常。

    
    
    class EventJsonAdapter {
      @FromJson Event eventFromJson(EventJson eventJson) {
        Event event = new Event();
        event.title = eventJson.title;
        event.beginDateAndTime = eventJson.begin_date + " " + eventJson.begin_time;
        return event;
      }
    
      @ToJson EventJson eventToJson(Event event) {
        EventJson json = new EventJson();
        json.title = event.title;
        json.begin_date = event.beginDateAndTime.substring(0, 8);
        json.begin_time = event.beginDateAndTime.substring(9, 14);
        return json;
      }
    }

    我们再次注册莫希适配器。

    
    
    Moshi moshi = new Moshi.Builder()
        .add(new EventJsonAdapter())
        .build();

    现在我们可以用磨石直接解析JSON到一个事件

    
    
    JsonAdapter<Event> jsonAdapter = moshi.adapter(Event.class);
    Event event = jsonAdapter.fromJson(json);

    优雅地失败

    自动数据绑定几乎感觉像魔术。但不同的是黑魔法,通常伴随着反射,磨石旨在帮助你当事情出错。

    
    
    JsonDataException: Expected one of [CLUBS, DIAMONDS, HEARTS, SPADES] but was ANCHOR at path $.visible_cards[2].suit
      at com.squareup.moshi.JsonAdapters$11.fromJson(JsonAdapters.java:188)
      at com.squareup.moshi.JsonAdapters$11.fromJson(JsonAdapters.java:180)
        ...

    莫希总是抛出一个标准的java.io.IOException异常,如果有一个错误读取JSON文档,或者如果它是畸形的。它抛出一个JsonDataException如果JSON文件是良好的,但不符合预期的格式。

    建立在奥基奥

    莫希使用奥基奥简单而功能强大的I / O。这是一个很好的补充,OkHttp,它可以共享缓冲段的最大效率。

    从GSON借用

    莫希使用相同的流媒体和约束机制为GSON如果你是一个GSON用户,你会发现莫希工作方式类似。如果您尝试莫希和不爱它,你甚至可以迁移到GSON没有太多的暴力!

    但是,这两个库有几个重要的区别:

    • 莫希具有较少的内置类型的适配器。例如,您需要配置自己的日期适配器。大多数绑定库将编码不管你扔他们。莫希拒绝序列化的平台类型(java中。*使用javax。*,和Android系统。*)无用户提供类型的适配器。这是为了防止意外锁定自己特定的JDK或Android版 本。
    • 莫希较少配置的。有没有现场的命名策略,版本控制,例如创作者,或长系列化策略。相反,命名字段visibleCards和使用策略类将其转换成visible_cards,磨石要你只是名称的字段visible_cards,因为它出现在JSON。
    • 莫希没有一个JsonElement模式。相反,它只是使用内置的类型,如列表和 地图
    • 没有HTML安全转义。 GSON编码= u003d默认情况下,以便它可以在HTML中被安全编码,无需额外转义。莫希自然编码它(如=),并假定HTML编码器-如果有的话-会做自己的工作。

    与@Json自定义字段名称

    莫希最适合当你的JSON对象和Java对象具有相同的结构。但是,当他们不这样做,磨石有注释定制数据绑定。

    使用@Json指定的Java如何字段映射到JSON的名字。这是必要的,当JSON名称包含空格或者未在Java字段名称中不允许其他字符。例如,这个JSON有包含空格的字段名称:

    
    
    {
      "username": "jesse",
      "lucky number": 32
    }

    随着@Json其相应的Java类很简单:

    
    
    class Player {
      String username;
      @Json(name = "lucky number") int luckyNumber;
    
      ...
    }

    由于JSON字段名始终与他们的Java领域的定义,磨石使得Java和JSON之间航行时很容易找到的字段。

    与@JsonQualifier交替类型的适配器

    使用@JsonQualifier自定义类型是如何编码的某些字段,而不无处不在改变其编码。这种工作方式类似于在预选赛中的注释依赖注入工具,如匕首和吉斯。

    下面是两个整数和颜色的JSON消息:

    
    
    {
      "width": 1024,
      "height": 768,
      "color": "#ff0000"
    }

    按照惯例,Android的程序也使用INT的颜色:

    
    
    class Rectangle {
      int width;
      int height;
      int color;
    }

    但是,如果我们编码上面的Java类JSON,颜色不正确编码!

    
    
    {
      "width": 1024,
      "height": 768,
      "color": 16711680
    }

    解决方法是定义一个限定注解,注解本身@JsonQualifier

    
    
    @Retention(RUNTIME)
    @JsonQualifier
    public @interface HexColor {
    }

    下一步将此@HexColor注释相应字段:

    
    
    class Rectangle {
      int width;
      int height;
      @HexColor int color;
    }

    最后定义一个类型的适配器来处理它:

    
    
    /** Converts strings like #ff0000 to the corresponding color ints. */
    class ColorAdapter {
      @ToJson String toJson(@HexColor int rgb) {
        return String.format("#%06x", rgb);
      }
    
      @FromJson @HexColor int fromJson(String rgb) {
        return Integer.parseInt(rgb.substring(1), 16);
      }
    }

    使用@JsonQualifier当您需要为同一型号不同JSON编码。大部分程序不应该需要这个@JsonQualifier,但它是为那些确实非常方便。

    下载

    下载最新的JAR或通过Maven的依赖:

    
    
    <dependency>
      <groupId>com.squareup.moshi</groupId>
      <artifactId>moshi</artifactId>
      <version>1.1.0</version>
    </dependency>

    or Gradle:

    compile 'com.squareup.moshi:moshi:1.1.0'
    
    下载地址https://github.com/square/moshi/archive/master.zip

     

  • 相关阅读:
    mysql 优化(包含sql语句的书写)
    tomcat优化
    MySQL——修改root密码的4种方法(以windows为例)
    实现窗口中的文档自动向上滚动,方便阅读
    处理文本框的鼠标事件,判断鼠标的状态
    通过给事件处理程序传递this参数,获取事件源对象的引用。单机提交按钮时在信息框中显示用户输入的字符。
    在标签的事件属性字符串中编写程序,检查用户输入的密码明文
    通过使用浏览器对象模型,输出当前浏览器窗口中打开的文档的URL信息,并将显示在窗口中。
    创建一个卡片对象,卡片上标有“名字”、“地址”和“电话”等信息。名片对象提供一个方法以输出这些信息。
    测试Array对象的sort方法的作用。将1985,1970,1999,1998,2000,1963这些年份按升序输出。
  • 原文地址:https://www.cnblogs.com/miaoqing/p/5192430.html
Copyright © 2011-2022 走看看