阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

使用JSON

28次阅读
没有评论

共计 3131 个字符,预计需要花费 8 分钟才能阅读完成。

前面我们讨论了 XML 这种数据格式。XML 的特点是功能全面,但标签繁琐,格式复杂。在 Web 上使用 XML 现在越来越少,取而代之的是 JSON 这种数据结构。

JSON 是 JavaScript Object Notation 的缩写,它去除了所有 JavaScript 执行代码,只保留 JavaScript 的对象格式。一个典型的 JSON 如下:

{
    "id": 1,
    "name": "Java 核心技术",
    "author": {
        "firstName": "Abc",
        "lastName": "Xyz"
    },
    "isbn": "1234567",
    "tags": ["Java", "Network"]
}

JSON 作为数据传输的格式,有几个显著的优点:

  • JSON 只允许使用 UTF- 8 编码,不存在编码问题;
  • JSON 只允许使用双引号作为 key,特殊字符用 \ 转义,格式简单;
  • 浏览器内置 JSON 支持,如果把数据用 JSON 发送给浏览器,可以用 JavaScript 直接处理。

因此,JSON 适合表示层次结构,因为它格式简单,仅支持以下几种数据类型:

  • 键值对:{"key": value}
  • 数组:[1, 2, 3]
  • 字符串:"abc"
  • 数值(整数和浮点数):12.34
  • 布尔值:truefalse
  • 空值:null

浏览器直接支持使用 JavaScript 对 JSON 进行读写:

// JSON string to JavaScript object:
jsObj = JSON.parse(jsonStr);

// JavaScript object to JSON string:
jsonStr = JSON.stringify(jsObj);

所以,开发 Web 应用的时候,使用 JSON 作为数据传输,在浏览器端非常方便。因为 JSON 天生适合 JavaScript 处理,所以,绝大多数 REST API 都选择 JSON 作为数据传输格式。

现在问题来了:使用 Java 如何对 JSON 进行读写?

在 Java 中,针对 JSON 也有标准的 JSR 353 API,但是我们在前面讲 XML 的时候发现,如果能直接在 XML 和 JavaBean 之间互相转换是最好的。类似的,如果能直接在 JSON 和 JavaBean 之间转换,那么用起来就简单多了。

常用的用于解析 JSON 的第三方库有:

  • Jackson
  • GSON
  • JSON-lib

注意到上一节提到的那个可以解析 XML 的浓眉大眼的 Jackson 也可以解析 JSON!因此我们只需要引入以下 Maven 依赖:

  • com.fasterxml.jackson.core:jackson-databind:2.12.0

就可以使用下面的代码解析一个 JSON 文件:

InputStream input = Main.class.getResourceAsStream("/book.json");
ObjectMapper mapper = new ObjectMapper();
// 反序列化时忽略不存在的 JavaBean 属性:
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Book book = mapper.readValue(input, Book.class);

核心代码是创建一个 ObjectMapper 对象。关闭 DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES 功能使得解析时如果 JavaBean 不存在该属性时解析不会报错。

把 JSON 解析为 JavaBean 的过程称为反序列化。如果把 JavaBean 变为 JSON,那就是序列化。要实现 JavaBean 到 JSON 的序列化,只需要一行代码:

String json = mapper.writeValueAsString(book);

要把 JSON 的某些值解析为特定的 Java 对象,例如LocalDate,也是完全可以的。例如:

{
    "name": "Java 核心技术",
    "pubDate": "2016-09-01"
}

要解析为:

public class Book {public String name;
    public LocalDate pubDate;
}

只需要引入标准的 JSR 310 关于 JavaTime 的数据格式定义至 Maven:

  • com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.12.0

然后,在创建 ObjectMapper 时,注册一个新的JavaTimeModule

ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule());

有些时候,内置的解析规则和扩展的解析规则如果都不满足我们的需求,还可以自定义解析。

举个例子,假设 Book 类的 isbn 是一个BigInteger

public class Book {public String name;
	public BigInteger isbn;
}

但 JSON 数据并不是标准的整形格式:

{
    "name": "Java 核心技术",
    "isbn": "978-7-111-54742-6"
}

直接解析,肯定报错。这时,我们需要自定义一个IsbnDeserializer,用于解析含有非数字的字符串:

public class IsbnDeserializer extends JsonDeserializer<BigInteger> {public BigInteger deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {// 读取原始的 JSON 字符串内容:
        String s = p.getValueAsString();
        if (s != null) {try {return new BigInteger(s.replace("-", ""));
            } catch (NumberFormatException e) {throw new JsonParseException(p, s, e);
            }
        }
        return null;
    }
}

然后,在 Book 类中使用注解标注:

public class Book {public String name;
    // 表示反序列化 isbn 时使用自定义的 IsbnDeserializer:
    @JsonDeserialize(using = IsbnDeserializer.class)
    public BigInteger isbn;
}

类似的,自定义序列化时我们需要自定义一个 IsbnSerializer,然后在Book 类中标注 @JsonSerialize(using = ...) 即可。

反序列化

在反序列化时,Jackson 要求 Java 类需要一个默认的无参数构造方法,否则,无法直接实例化此类。存在带参数构造方法的类,如果要反序列化,注意再提供一个无参数构造方法。

对于 enum 字段,Jackson 按 String 类型处理,即:

class Book {public DayOfWeek start = MONDAY;
}

序列化为:

{
    "start": "MONDAY"
}

对于 record 类型,Jackson 会自动找出它的带参数构造方法,并根据 JSON 的 key 进行匹配,可直接反序列化。对 record 类型的支持需要版本 2.12.0 以上。

练习

使用 Jackson 解析 JSON。

下载练习

小结

JSON 是轻量级的数据表示方式,常用于 Web 应用;

Jackson 可以实现 JavaBean 和 JSON 之间的转换;

可以通过 Module 扩展 Jackson 能处理的数据类型;

可以自定义 JsonSerializerJsonDeserializer来定制序列化和反序列化。

正文完
星哥说事-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2024-08-05发表,共计3131字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中