用 Jackson 映射一个可以有不同类型的 JSON 字段?

2024-02-07

我从 Web 服务获取 JSON,并且无法影响 JSON 格式。下面的 JSON 代码只是一个示例来说明问题。场cars可以是一个包含以下内容的对象Car对象,也可以是空字符串。如果我可以更改网络服务,我会将空字符串更改为空对象,例如"cars" : {}代替"cars" : "".

当尝试将 JSON 映射到此 Java 对象时:

public class Person {
    public int id;
    public String name;
    public Map<String, Car> cars;
}

这有效:

{
    "id" : "1234",
    "name" : "John Doe",
    "cars" : {
        "Tesla Model S" : {
            "color" : "silver",
            "buying_date" : "2012-06-01"
        },
        "Toyota Yaris" : {
            "color" : "blue",
            "buying_date" : "2005-01-01"
        }
    }
}

这失败了:

{
    "id" : "1",
    "name" : "The Dude",
    "cars" : ""
}

在杰克逊处理此案的最佳方式是什么?如果有空字符串,我想得到null对于现场cars。我尝试使用ACCEPT_EMPTY_STRING_AS_NULL_OBJECT,但这没有帮助。


现场汽车可以包含汽车对象列表 ... 这有效:

{
    "id" : "1234",
    "name" : "John Doe",
    "cars" : {
        "Tesla Model S" : {
            "color" : "silver",
            "buying_date" : "2012-06-01"
        },
        "Toyota Yaris" : {
            "color" : "blue",
            "buying_date" : "2005-01-01"
        }
    }
}

“cars”元素值不是列表(也称为数组)。它是一个JSON对象,也可以认为是一个map类型的集合,但它不是一个列表。

因此,重新表述这个问题,目标是将有时是对象有时是空字符串的 JSON 反序列化为 JavaMap.

为了解决这个问题,我很惊讶ACCEPT_EMPTY_STRING_AS_NULL_OBJECT http://jackson.codehaus.org/1.8.2/javadoc/org/codehaus/jackson/map/DeserializationConfig.Feature.html#ACCEPT_EMPTY_STRING_AS_NULL_OBJECT没用。我建议将问题记录在http://jira.codehaus.org/browse/JACKSON http://jira.codehaus.org/browse/JACKSON.

你可以实施自定义反序列化 http://wiki.fasterxml.com/JacksonHowToCustomDeserializers。以下是一个示例解决方案。如果目标数据结构有其他Map参考文献,那么这个解决方案就需要做相应的改变。

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.ObjectCodec;
import org.codehaus.jackson.Version;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.JsonDeserializer;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.module.SimpleModule;
import org.codehaus.jackson.type.TypeReference;

public class Foo
{
  public static void main(String[] args) throws Exception
  {
    SimpleModule module = new SimpleModule("CarsDeserializer", Version.unknownVersion());
    module.addDeserializer(Map.class, new CarsDeserializer());

    ObjectMapper mapper = new ObjectMapper().withModule(module);

    Person person1 = mapper.readValue(new File("input1.json"), Person.class);
    System.out.println(mapper.writeValueAsString(person1));
    // {"id":1234,"name":"John Doe","cars":{"Tesla Model S":{"color":"silver","buying_date":"2012-06-01"},"Toyota Yaris":{"color":"blue","buying_date":"2005-01-01"}}}

    Person person2 = mapper.readValue(new File("input2.json"), Person.class);
    System.out.println(mapper.writeValueAsString(person2));
    // {"id":1,"name":"The Dude","cars":{}}
  }
}

class Person
{
  public int id;
  public String name;
  public Map<String, Car> cars;
}

class Car
{
  public String color;
  public String buying_date;
}

class CarsDeserializer extends JsonDeserializer<Map<String, Car>>
{
  @Override
  public Map<String, Car> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException,
      JsonProcessingException
  {
    ObjectCodec codec = jp.getCodec();
    JsonNode node = codec.readTree(jp);
    if (!"".equals(node.getTextValue()))
    {
      ObjectMapper mapper = new ObjectMapper();
      return mapper.readValue(node, new TypeReference<Map<String, Car>>() {});
    }
    return new HashMap<String, Car>(); // or return null, if preferred
  }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用 Jackson 映射一个可以有不同类型的 JSON 字段? 的相关文章

随机推荐

  • 如何在 DRF ViewSet 中完全不允许 PUT 方法但允许 PATCH?

    PUT and PATCH都是同一个 mixin 的一部分 更新模型混合 http www django rest framework org api guide generic views updatemodelmixin 所以如果我像这
  • 在 Bash 中获取日期(当前时间前一天)

    如何在 Bash 中打印当前时间前一天的日期 如果你有 GNU 日期并且我理解正确的话 date Y m d d yesterday 2009 11 09 or date Y m d d 1 day ago 2009 11 09
  • 如何在接口上实现静态方法?

    我有一个从 C 调用的第 3 方 C DLL 这些方法是静态的 我想将其抽象出来进行一些单元测试 因此我创建了一个包含静态方法的接口 但现在我的程序出现错误 修饰符 static 对此项目无效 MyMethod cannot be acce
  • 遍历networkx中图的级别顺序

    我正在尝试转换DiGraph成n叉树并按层序或BFS显示节点 我的树与此类似 但更大 为简单起见 使用以下示例 G networkx DiGraph G add edges from n n1 n n2 n n3 G add edges f
  • 行未在 ios 上使用 xamarin 表单调整大小

    我在 xamarin 表单中使用列表视图 它将在行点击时展开行 并在展开行时折叠行 该逻辑在 android 中工作正常 但我在 IOS 上遇到问题 有没有办法调整高度大小IOS 提前致谢 相反 请使用堆栈布局并点击即可切换堆栈布局的可见性
  • 目录价格规则 以编程方式“应用规则”

    我以编程方式创建了一个目录价格规则 它工作正常 所以我的问题是 我需要使用管理员登录并需要单击按钮 应用规则 否则 折扣不适用于 magento 商店 所以我需要以编程方式 应用规则 但我不知道该怎么做 任何帮助或建议将不胜感激 You c
  • 将 UIViewController 推到 UITabBar 之上

    我有一个UIViewController called ListVC ListVC has a UITabBar用户可以使用它来切换选项卡 它也有UINavigationController In ListVC我有一个按钮 我想推送一个名为
  • cassandra 中列的默认排序顺序?

    我正在阅读教程 其中讲师说行中列的默认顺序是UTF8 tye 但他没有进一步谈及这一点 我不明白这是什么意思 特别是如果我的列是不同类型的 例如int timestamp etc 另外 我如何将列上的排序顺序指定为 UTF8 类型 以外的其
  • 如何在每个 as (ember 1.11 beta3) 中设置 itemController?

    我想尝试使用 each content as product index index each 但我的应用程序有 itemContoller 如下所示 each product in content itemController produ
  • 最大执行时间错误处理

    我有一个脚本有时会给出最大执行时间达到错误 这是正常现象 不是问题 问题是在这种情况下我会写出具体的错误消息 我该怎么做呢 function say goodbye if connection aborted Perform some ac
  • 如何在 iOS PhoneGap 应用程序中显示自定义启动屏幕旋转器(即白色旋转器)?

    是否可以将默认启动屏幕旋转器颜色更改为白色 将其用于 Spinner hzactivityindicatorview https www cocoacontrols com controls hzactivityindicatorview
  • 如何将 matplotlib 动画转换为 HTML5

    下面是 matplotlib 动画图的代码和here https matplotlib org api as gen matplotlib animation Animation html就是如何保存它 from IPython displ
  • Webpack - 更新 HTML 以包含最新的 [hashed] 包的最佳方式

    我正在使用 webpack 生成散列包文件名 假设我使用静态 HTML CSS 和 JS 自动更新的最佳方法是什么index html指向最新的捆绑包 例如 update to no change 每次有新的捆绑包版本可用时都会自动进行 令
  • 显示12小时和24小时时间

    我想制作一个显示当前时间的网页 当点击 12小时制 按钮时 div区域将显示12小时制的时间 当点击 24小时制 按钮时 分区区域中的时间将以24小时制显示 目前 单击这些按钮时不会发生任何事情 帮助 HTML div div br
  • 如何使用 Python 的 zipfile 模块设置 ZIP 文件中文件的权限(属性)?

    当我从使用 Python 创建的 ZIP 文件中提取文件时zipfile http docs python org library zipfile html模块 所有文件都是不可写 只读等 该文件是在 Linux 和 Python 2 5
  • 用户登录后重定向

    我对 Angular 还很陌生 现在我只是想按照我的意愿设置所有路线并使其工作 Setup 当用户导航到某些页面时 settings对于此示例 应用程序应检查是否有用户已登录 如果有则照常继续 否则用户应该转到登录页面 login 我想要什
  • JQuery 方法和 DOM 属性

    我很困惑何时可以使用 DOM 属性以及何时可以在 Jquery 对象上使用 Jquery 方法 比如说 我使用选择器 var elemSel myDiv find id select 此时 elemSel 是一个 jquery 对象 我将其
  • 无法获取文件创建日期?

    在我的应用程序中 我创建一个目录 然后以下代码起作用 NSDictionary fileAttributes fileManager fileAttributesAtPath trackDirectory traverseLink YES
  • 如何从 lldb 执行一个块(由指针标识)

    我在 iOS 模拟器的 lldb 调试器中 并且有一个块的地址 我想尝试执行它 我尝试了想到的第一件事 见下文 但它不起作用 有没有办法做到这一点 lldb po 0x2c7140 int 2 2912576 lt NSGlobalBloc
  • 用 Jackson 映射一个可以有不同类型的 JSON 字段?

    我从 Web 服务获取 JSON 并且无法影响 JSON 格式 下面的 JSON 代码只是一个示例来说明问题 场cars可以是一个包含以下内容的对象Car对象 也可以是空字符串 如果我可以更改网络服务 我会将空字符串更改为空对象 例如 ca