杰克逊:引用同一个对象

2024-05-02

在某些情况下,主体(例如 JSON 主体)中序列化或非序列化的数据包含对同一对象的引用。例如,包含球员列表以及由这些球员组成的球队列表的 JSON 正文:

{
  "players": [
    { "name": "Player 1" },
    { "name": "Player 2" },
    { "name": "Player 3" },
    { "name": "Player 4" },
    { "name": "Player 5" },
    { "name": "Player 6" },
    { "name": "Player 7" },
    { "name": "Player 8" }
  ],
  "teams": [
    {
      "name": "Team 1",
      "players": [
        { "name": "Player 1"},
        { "name": "Player 2"}
      ]
    },
    {
      "name": "Team 2",
      "players": [
        { "name": "Player 3"},
        { "name": "Player 4"}
      ]
    },
    {
      "name": "Team 3",
      "players": [
        { "name": "Player 5"},
        { "name": "Player 6"}
      ]
    },
    {
      "name": "Team 4",
      "players": [
        { "name": "Player 7"},
        { "name": "Player 8"}
      ]
    }
  ]
}

正如你所能想象的那样Player X引用同一个对象,但我们可能最终会遇到不想要的情况:Player X由不同的对象来表示。

我想知道解决这些情况的最佳和最常见的方法是什么。我可以想到几种方法来做到这一点:

  1. 添加 ID 属性Player班级。我的设计不包含 ID,因为不需要它。识别对象的方法是通过它的引用,如果它们包含在集合中,则通过它们在其中的位置(如果集合有位置)。这可能被认为是一种不好的做法,但我是故意这样做的,除非有必要,否则我不打算改变它。
  2. 还有一个玩家 ID,但它不会将球队序列化/反序列化为玩家列表,而只是一个 ID 列表。 JSON 正文中包含的信息将丢失,但我们将拥有更紧凑的数据。
  3. 坚持我的无 ID 设计,与上一点类似,我可以有一个位置列表(实际上它是一个玩家 ID,因为它们充当识别手段),所以数字0指的是在比赛中处于第一位置的球员players list.
  4. 改变合同并拥有具有独特名字的球员。有了这个,我们现在就可以拥有一个 ID,而不必向类添加新属性。然而我认为这是一个坏主意,因为不一定所有玩家都应该有不同的名字。

最好的方法是什么?通常做什么?您有不同的建议吗?


我达到了接近问题要求的东西: 我用的是杰克逊的对象识别特征 http://wiki.fasterxml.com/JacksonFeatureObjectIdentity它允许定义某个属性的值来标识 POJO 的不同实例:

@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, 
        property="name", scope=Player.class)
public class Player
{
    public String name;

    public Player() {}
    public Player(String name) { this.name = name; }

    public String toString() {
        // prints name and java object id 
        return name + "-" + super.toString();
    }
}

这是使用的 POJO 的其余部分:

public class League
{
    public List<Player> players;
    public List<Team> teams;
}

public class Team
{
    public String name;
    public List<Player> players;

    public Team() {}
    public Team(String name) { this.name = name; }

    public String toString() {
        return name + "-" + super.toString() + ":" + players.toString();
    }
}

测试方法:

public static void main(String[] args)
{
    ObjectMapper objectMapper = new ObjectMapper();

    try (Reader reader = new FileReader("C:/Temp/xx.json")) {
        League l = objectMapper.readValue(reader, League.class);
        System.out.println("l.players");
        System.out.println(l.players);
        System.out.println("l.teams");
        System.out.println(l.teams);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

输出清楚地表明玩家和团队中使用了相同的对象:

l.players
[Player 1-test.JSONTest$Player@641147d0, Player 2-test.JSONTest$Player@6e38921c, Player 3-test.JSONTest$Player@64d7f7e0, Player 4-test.JSONTest$Player@27c6e487, Player 5-test.JSONTest$Player@49070868, Player 6-test.JSONTest$Player@6385cb26, Player 7-test.JSONTest$Player@38364841, Player 8-test.JSONTest$Player@28c4711c]
l.teams
[Team 1-test.JSONTest$Team@59717824:[Player 1-test.JSONTest$Player@641147d0, Player 2-test.JSONTest$Player@6e38921c], Team 2-test.JSONTest$Team@146044d7:[Player 3-test.JSONTest$Player@64d7f7e0, Player 4-test.JSONTest$Player@27c6e487], Team 3-test.JSONTest$Team@1e9e725a:[Player 5-test.JSONTest$Player@49070868, Player 6-test.JSONTest$Player@6385cb26], Team 4-test.JSONTest$Team@15d9bc04:[Player 7-test.JSONTest$Player@38364841, Player 8-test.JSONTest$Player@28c4711c]]

到目前为止一切都很好,那么为什么要“接近要求​​”呢? 我必须稍微更改输入 json,以便 Jackson 能够正确识别团队中的球员是对球员列表中球员的引用:

{
  "players": [
    { "name": "Player 1" },
    { "name": "Player 2" },
    { "name": "Player 3" },
    { "name": "Player 4" },
    { "name": "Player 5" },
    { "name": "Player 6" },
    { "name": "Player 7" },
    { "name": "Player 8" }
  ],
  "teams": [
    {
      "name": "Team 1",
      "players": [ "Player 1", "Player 2"]
    },
    {
      "name": "Team 2",
      "players": [ "Player 3", "Player 4"]
    },
    {
      "name": "Team 3",
      "players": [ "Player 5", "Player 6"]
    },
    {
      "name": "Team 4",
      "players": [ "Player 7", "Player 8"]
    }
  ]
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

杰克逊:引用同一个对象 的相关文章

随机推荐

  • AWS ECS 重启策略

    我检查了在 ECS 集群中运行的一个 docker 容器 它的重启策略为空白 HostConfig RestartPolicy Name 我不确定 ECS 在发生故障时会做什么 但我想将策略更改为在实例中运行的 cmd 失败时重新启动容器实
  • 如何使用 JavaScript 或 jQuery 获取 html 元素的比例值?

    我想知道如何获得元素的比例值 我努力了 element css webkit transform 返回matrix scaleX 0 0 scaleY 0 0 有没有办法得到scaleX and scaleY only 找出文档和元素之间的
  • PrimaryContext如何登录域服务器

    我有以下 C 代码 用于连接到我的域服务器并对其执行一些操作 我的计算机上一切正常 我可以正常运行所有命令 我的问题是 连接服务器使用什么凭据 我假设它使用当前用户的凭据 所以我真正的问题是这对普通用户有效吗 我是管理员 它在我的机器上运行
  • 如何为 HTML 验证提供自定义验证错误消息?

    当我使用默认 HTML 验证时 它会显示默认错误消息 这不是我想向客户显示的 我需要自定义消息并为每个验证提供不同的信息 例如最小 最大 类型和要求 例如 该字段为必填项 值不匹配 参考传统的HTML代码
  • 将数据发送到 parse.com 并更新 Angular $scope

    我正在将数据发送到 parse com 上的类 我想运行此函数并更新 scope无需重新加载视图 创建一个Programme运行下面的函数工作正常 但是有时在创建新程序后不会更新视图 并且需要刷新页面 当调用整个函数时 如底部所示 getP
  • 如何在 Objective-C 中创建委托?

    我知道代表如何工作 也知道如何使用它们 但我该如何创建它们呢 Objective C 委托是一个已分配给delegate属性另一个对象 要创建一个 您需要定义一个实现您感兴趣的委托方法的类 并将该类标记为实现委托协议 例如 假设您有一个UI
  • Spark parquet 分区:大量文件

    我正在尝试利用 Spark 分区 我试图做类似的事情 data write partitionBy key parquet location 这里的问题是每个分区都会创建大量镶木地板文件 如果我尝试从根目录读取 则会导致读取速度变慢 为了避
  • 使用 javascript onClick 播放 mp3 文件

    我正在播放 mp3 文件 只是 javascript onClick 下面是我的代码 Music File 1
  • 检测已退款的托管应用内购买 android IAP 2.0.3

    我无法弄清楚如何使用 Android 检测何时为托管 不可消费 应用内产品发放退款com android billingclient billing 2 0 3 这个问题似乎相当深 尽管我可能让它变得比应有的更复杂 首先 我进行了一次测试购
  • IdentityServer4 - 直接从外部提供商登录

    我已经实现了从 Azure AD 登录的选项 我使用的客户端类型是混合型 因此 现在 当用户在我的应用程序上输入受限控制时 他将被重定向到登录页面 在 IdentityServer 应用程序站点上 他可以在其中输入用户名和密码 也可以使用
  • 使用 Ref 作为 Fn::Sub 内部函数中的第一个参数

    我在编译模板时遇到了非常奇怪的问题 我在其中引用了一个字符串参数Fn Sub 而docs http docs aws amazon com AWSCloudFormation latest UserGuide intrinsic funct
  • 为什么没有 styleMask:NSTitledWindowMask 的 NSWindow 不能成为 keyWindow?

    问题 我有一个窗口 mainWindow 和另一个窗口childWindow添加到mainWindow childWindow 是一种WindowExt班级 我为 catch 方法调用定义了这个类 NSWindow becomeKeyWin
  • Flutter Firestore 日期

    我知道这是重复的 但由于我无法找到正确的方法 所以请不要将其标记为重复 我想将日期类型正确设置为Firestore扑腾中 我试过DateTime now 但是当我检索它时错误说 不支持的值 FIRTimestamp FIRTimestamp
  • 我应该担心“窗口未定义”JSLint 严格模式错误吗?

    这不会在严格模式下通过 JSLint use strict function w w alert w window 来自 jslint com 的错误如下所示 第 4 行第 3 行字符出现问题 window 未定义 window 隐含全局
  • 在锁定屏幕上显示 UWP 控件

    我做了什么 我得到的要求是用户需要能够通过 Windows 锁定屏幕启动我的应用程序 搜索 www 后发现 从锁定屏幕连接热键非常困难 如果不是不可能的话 然后我发现这个帖子 https stackoverflow com question
  • 为什么使用散列而不是点来选择 Scala 类型成员?

    在 Scala 中 从类中选择类型的语法与从类中选择其他任何内容的语法不同 因为前者使用散列而不是点作为选择运算符 这是为什么 示例 如果我们有这样的课程 class Example type Foo String 为什么我们要从这样的类中
  • 在 Django 1.9 中使用信号

    在 Django 1 8 中 我能够使用信号执行以下操作 一切顺利 init py from signals import 信号 py receiver pre save sender Comment def process hashtag
  • 如何为特定存储库配置 AWS CodeCommit 配置文件

    我有以下问题 作为我工作的一部分 我处理多个 AWS 账户 每个账户都有一个单独的 AWS CodeCommit 存储库和特定于账户的 IAM 用户 这会导致不同的用户 ID 我想找到一种方法来配置我的 ssh 以根据存储库访问不同的帐户
  • 有没有办法在Python中调用子类定义的方法?

    The init 方法定义了创建类的实例时要执行的操作 创建子类时我可以做类似的事情吗 假设我有抽象类Entity class Entity def onsubclasscreation cls for var in cls annotat
  • 杰克逊:引用同一个对象

    在某些情况下 主体 例如 JSON 主体 中序列化或非序列化的数据包含对同一对象的引用 例如 包含球员列表以及由这些球员组成的球队列表的 JSON 正文 players name Player 1 name Player 2 name Pl