【问题标题】:Serialize a UUID as canonical hex string in JSON using JSON-B使用 JSON-B 将 UUID 序列化为 JSON 中的规范十六进制字符串
【发布时间】:2018-12-31 10:35:14
【问题描述】:

UUID

universally unique identifier (UUID) 是一个 128 位的值。在 Java 中由 java.util.UUID 类表示。

十六进制字符串

为了显示和序列化,它被规范地格式化为 36 个字符的十六进制字符串,以连字符分隔的五组排列。 For example:
fd95cb46-8ec3-11e8-9eb6-529269fb1459

当使用 Java 标准的 XML 和 JSON API 进行序列化时,我期望这个十六进制字符串。适用于 XML,但不适用于 JSON。我没有为 XML 或 JSON 使用任何类型的注释。我简单的POJOXMLJSON 一无所知。

XML = 成功????

当我使用JSR 222: JavaTM Architecture for XML Binding (JAXB) 2.0 的标准 XML 绑定框架生成 XML 时,成功。我按预期得到了十六进制字符串。查看此 sn-p 的最后一个元素:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<panel>
    <connected>3.4kVA</connected>
    <fedFrom>PANEL 'EHE1' &amp; ATS-EM</fedFrom>
    <grounding>ground bus</grounding>
    <id>89d14b92-35ae-4c0c-b61d-ea8dbdeb324b</id>

JSON = 失败????

当我通过JSR 367: JavaTM API for JSON Binding (JSON-B) 的标准 JSON 绑定框架运行相同的 panel 对象时,失败。我得到的是数字,而不是预期的十六进制字符串。

{"connected":"3.4kVA","fedFrom":"PANEL 'EHE1' & ATS-EM","grounding":"ground bus","id":{"leastSignificantBits":-5323841289984462261,"mostSignificantBits":-8515942329042973684},

如果滚动,您将看到名为 id 的 UUID 显示为一对数字而不是十六进制字符串:

"id":{"leastSignificantBits":-5323841289984462261,"mostSignificantBits":-8515942329042973684}

有没有办法让 JSON 绑定像 XML 绑定一样工作?我想要十六进制字符串,而不是一对 64 位数字。

当然,这个封送的值在解组时应该可以工作,重新水合到 Java 对象中。

【问题讨论】:

  • UUID 不是受支持的 JSON-B 类型,因此您可能必须实现自己的适配器或序列化器/反序列化器 (json-b.net/users-guide.html)。
  • @Philipp UUID 也不是 XML 已知的数据类型。只需致电java.util.UUID::toString 即可完成工作。然而,JSON-B 正在竭尽全力生成一对 64 位数字。
  • 你可以称它为“不碍事”,但从 JSON-B 的角度来看,UUID 只是一个对象(类型未知),它有两个属性(longs), JSON-B 将其序列化为您在输出中观察到的两个属性:leastSignificantBitsmostSignificantBits。顺便提一句。其他 JSON 映射器有/有同样的问题,例如,GSON:github.com/google/gson/issues/79

标签: java json data-binding binding jsonb-api


【解决方案1】:

JSON-B 规范没有提及 UUID 类型,因此它是否提供开箱即用的(反)序列化器取决于实现。但是,如果您使用的是 Eclipse Yasson(JSON-B ref impl),它会默认提供一个 UUID(反)序列化程序。我不确定其他 JSON-B impls(例如 Apache Johnzon)默认提供什么。

如果您使用的是 Yasson,我建议您在 their GitHub repo 上打开一个错误,因为这应该可以。


自定义方式

如果您使用默认不提供 UUID 适配器的 JSON-B 实现,您可以创建并注册自己的类型适配器:

public static class MyUUIDAdapter implements JsonbAdapter<UUID, String> {

    @Override
    public String adaptToJson(UUID obj) throws Exception {
        return obj.toString();
    }

    @Override
    public UUID adaptFromJson(String obj) throws Exception {
        return UUID.fromString(obj);
    }

}

注册适配器最简单的方法是在创建Jsonb 实例时:

Jsonb jsonb = JsonbBuilder.create(new JsonbConfig().withAdapters(new MyUUIDAdapter()));

但是,如果您不控制 Jsonb 实例的实例化(例如 JAX-RS 在幕后进行),您可以注释字段/方法以使用适配器:

public class Panel {
    @JsonbTypeAdapter(MyUUIDAdapter.class)
    public UUID id;
}

【讨论】:

    猜你喜欢
    • 2023-04-08
    • 2020-08-22
    • 2022-01-07
    • 1970-01-01
    • 2019-07-27
    • 2018-01-31
    • 1970-01-01
    • 1970-01-01
    • 2010-11-21
    相关资源
    最近更新 更多