Jackson - 将内部对象列表反序列化为更高级别的列表

2024-02-13

使用 Spring Boot 和 Jackson,如何将包装/内部列表直接反序列化为外层列表?

例如,我有:

{
    "transaction": {
    "items": {
        "item": [
            {
                "itemNumber": "193487654",
                "itemDescription": "Widget",
                "itemPrice": "599.00",
                "itemQuantity": "1",
                "itemBrandName": "ACME",
                "itemCategory": "Electronics",
                "itemTax": "12.95"
            },
            {
                "itemNumber": "193487654",
                "itemDescription": "Widget",
                "itemPrice": "599.00",
                "itemQuantity": "1",
                "itemBrandName": "ACME",
                "itemCategory": "Electronics",
                "itemTax": "12.95"
            }
        ]
    },
    ...
    }
}

在 JSON 中,item是下面的一个列表items;但我想将其解析为名为的列表items,直接在transaction,而不是定义 DTOItems其中包含一个名为的列表item.

这可能吗?如何定义这个DTOItem?

public class TrasactionDTO {
    private List<Item> items;
    ...
}

public class Item {

}

这个问题类似,但没有解决问题。使用 Jackson 反序列化包装列表 https://stackoverflow.com/questions/27699538/deserialize-wrapped-list-using-jackson


我们需要实现自定义解串器。因为我们想跳过一个内部字段,所以我们的实现应该:

  1. {- 跳过起始对象
  2. "any_field_name"- 跳过任何字段名称。我们假设我们只有一个内部场。
  3. [{}, ..., {}]- 使用默认解串器List.
  4. }- 跳过结束对象

使用上述概念实现应该很容易:

public class InnerListDeserializer extends JsonDeserializer<List> implements ContextualDeserializer {

    private final JavaType propertyType;

    public InnerListDeserializer() {
        this(null);
    }

    public InnerListDeserializer(JavaType propertyType) {
        this.propertyType = propertyType;
    }

    @Override
    public List deserialize(JsonParser p, DeserializationContext context) throws IOException {
        p.nextToken(); // SKIP START_OBJECT
        p.nextToken(); // SKIP any FIELD_NAME

        List list = context.readValue(p, propertyType);

        p.nextToken(); // SKIP END_OBJECT

        return list;
    }

    @Override
    public JsonDeserializer<?> createContextual(DeserializationContext context, BeanProperty property) {
        return new InnerListDeserializer(property.getType());
    }
}

假设我们有JSON有效负载如下:

{
  "transaction": {
    "items": {
      "item": [
        {
          "itemNumber": "193487654",
          "itemDescription": "Widget",
          "itemPrice": "599.00",
          "itemQuantity": "1",
          "itemBrandName": "ACME",
          "itemCategory": "Electronics",
          "itemTax": "12.95"
        },
        {
          "itemNumber": "193487654",
          "itemDescription": "Widget",
          "itemPrice": "599.00",
          "itemQuantity": "1",
          "itemBrandName": "ACME",
          "itemCategory": "Electronics",
          "itemTax": "12.95"
        }
      ]
    },
    "name": "Pickle Rick"
  }
}

Above JSON我们可以映射到下面POJO课程:

@JsonRootName("transaction")
public class Transaction {

    private String name;
    private List<Item> items;

    @JsonDeserialize(using = InnerListDeserializer.class)
    public List<Item> getItems() {
        return items;
    }

    // getters, setters, toString
}

public class Item {

    private String itemNumber;

    // getters, setters, toString
}

为了证明它适用于许多不同的模型,让我们再介绍一个JSON有效负载:

{
  "product": {
    "products": {
      "innerArray": [
        {
          "id": "1234"
        }
      ]
    }
  }
}

还有两个POJO课程:

@JsonRootName("product")
class Product {

    private List<ProductItem> products;

    @JsonDeserialize(using = InnerListDeserializer.class)
    public List<ProductItem> getProducts() {
        return products;
    }

    // getters, setters, toString
}

class ProductItem {

    private String id;

    // getters, setters, toString
}

现在我们可以测试我们的解决方案:

import com.fasterxml.jackson.annotation.JsonRootName;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;

import java.io.File;
import java.io.IOException;
import java.util.List;

public class JSoupTest {

    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        mapper.enable(SerializationFeature.INDENT_OUTPUT);
        mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

        File jsonFile = new File("Path to 1-st JSON").getAbsoluteFile();
        File jsonFile1 = new File("Path to 2-nd JSON").getAbsoluteFile();

        System.out.println(mapper.readValue(jsonFile, Transaction.class));
        System.out.println(mapper.readValue(jsonFile1, Product.class));
    }
}

上面的例子打印:

Transaction{items=[Item{itemNumber=193487654}, Item{itemNumber=193487654}], name='Pickle Rick'}
Product{products=[ProductItem{id='1234'}]}

欲了解更多信息,请阅读:

  1. 自定义 Jackson 解串器获取当前字段类的访问权限 https://stackoverflow.com/questions/8944086/custom-jackson-deserializer-getting-access-to-current-field-class
  2. Jackson 中的自定义反序列化入门 https://www.baeldung.com/jackson-deserialization
  3. 杰克逊例外——问题和解决方案 https://www.baeldung.com/jackson-exception
  4. 杰克逊 UNWRAP_ROOT_VALUE https://fasterxml.github.io/jackson-databind/javadoc/2.9/com/fasterxml/jackson/databind/DeserializationFeature.html#UNWRAP_ROOT_VALUE
  5. 在 Spring 中配置 ObjectMapper https://stackoverflow.com/questions/7854030/configuring-objectmapper-in-spring
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Jackson - 将内部对象列表反序列化为更高级别的列表 的相关文章

  • jQuery AJAX 调用 Java 方法

    使用 jQuery AJAX 我们可以调用特定的 JAVA 方法 例如从 Action 类 该 Java 方法返回的数据将用于填充一些 HTML 代码 请告诉我是否可以使用 jQuery 轻松完成此操作 就像在 DWR 中一样 此外 对于
  • java.lang.IllegalStateException:应用程序 PagerAdapter 更改了适配器的内容,而没有调用 PagerAdapter#notifyDataSetChanged android

    我正在尝试使用静态类将值传递给视图 而不是使用意图 因为我必须传递大量数据 有时我会收到此错误 但无法找出主要原因是什么 Error java lang IllegalStateException The application s Pag
  • 检测并缩短字符串中的所有网址

    假设我有一条字符串消息 您应该将 file zip 上传到http google com extremelylonglink zip http google com extremelylonglink zip not https stack
  • 无法创建请求的服务[org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]-MySQL

    我是 Hibernate 的新手 我目前正在使用 Spring boot 框架并尝试通过 hibernate 创建数据库表 我知道以前也问过同样的问题 但我似乎无法根据我的环境找出如何修复错误 休眠配置文件
  • Eclipse Maven Spring 项目 - 错误

    I need help with an error which make me crazy I started to study Java EE and I am going through tutorial on youtube Ever
  • Spring Boot Data JPA 从存储过程接收多个输出参数

    我尝试通过 Spring Boot Data JPA v2 2 6 调用具有多个输出参数的存储过程 但收到错误 DEBUG http nio 8080 exec 1 org hibernate engine jdbc spi SqlStat
  • 如何对不同的参数类型使用相同的java方法?

    我的问题 我有 2 个已定义的记录 创建对象请求 更新对象请求 必须通过实用方法进行验证 由于这两个对象具有相同的字段 因此可以对这两种类型应用相同的验证方法 现在我只是使用两种方法进行重载 但它很冗长 public record Crea
  • 尝试将 Web 服务部署到 TomEE 时出现“找不到...的 appInfo”

    我有一个非常简单的项目 用于培训目的 它是一个 RESTful Web 服务 我使用 js css 和 html 创建了一个客户端 我正在尝试将该服务部署到 TomEE 这是我尝试部署时遇到的错误 我在这里做错了什么 刚刚遇到这个问题 我曾
  • 在javascript中解析json - 长数字被四舍五入

    我需要解析一个包含长数字的 json 在 java servlet 中生成 问题是长数字被四舍五入 当执行这段代码时 var s x 6855337641038665531 var obj JSON parse s alert obj x
  • Eclipse 选项卡宽度不变

    我浏览了一些与此相关的帖子 但它们似乎并不能帮助我解决我的问题 我有一个项目 其中 java 文件以 2 个空格的宽度缩进 我想将所有内容更改为 4 空格宽度 我尝试了 正确的缩进 选项 但当我将几行修改为 4 空格缩进时 它只是将所有内容
  • 使用 Newtonsoft 和 C# 反序列化嵌套 JSON

    我正在尝试解析来自 Rest API 的 Json 响应 我可以获得很好的响应并创建了一些类模型 我正在使用 Newtonsoft 的 Json Net 我的响应中不断收到空值 并且不确定我的模型设置是否正确或缺少某些内容 例如 我想要获取
  • java.io.Serialized 在 C/C++ 中的等价物是什么?

    C C 的等价物是什么java io Serialized https docs oracle com javase 7 docs api java io Serializable html 有对序列化库的引用 用 C 序列化数据结构 ht
  • 专门针对 JSP 的测试驱动开发

    在理解 TDD 到底是什么之前 我就已经开始编写测试驱动的代码了 在没有实现的情况下调用函数和类可以帮助我以更快 更有效的方式理解和构建我的应用程序 所以我非常习惯编写代码 gt 编译它 gt 看到它失败 gt 通过构建其实现来修复它的过程
  • 我如何在java中读取二进制数据文件

    因此 我正在为学校做一个项目 我需要读取二进制数据文件并使用它来生成角色的统计数据 例如力量和智慧 它的设置是让前 8 位组成一个统计数据 我想知道执行此操作的实际语法是什么 是不是就像读文本文件一样 这样 File file new Fi
  • 干净构建 Java 命令行

    我正在使用命令行编译使用 eclipse 编写的项目 如下所示 javac file java 然后运行 java file args here 我将如何运行干净的构建或编译 每当我重新编译时 除非删除所有内容 否则更改不会受到影响 cla
  • 如何通过SQL查询检查是否有JSON函数?

    有SQL 2016 中的 JSON 函数 https learn microsoft com en us sql t sql functions json functions transact sql例如 JSON VALUE JSON Q
  • 如何使用mockito模拟构建器

    我有一个建造者 class Builder private String name private String address public Builder setName String name this name name retur
  • 包 javax.el 不存在

    我正在使用 jre6 eclipse 并导入 javax el 错误 包 javax el 不存在 javac 导入 javax el 过来 这不应该是java的一部分吗 谁能告诉我为什么会这样 谢谢 米 EL 统一表达语言 是 Java
  • 在java中为组合框分配键

    我想添加一个JComboBox在 Swing 中这很简单 但我想为组合中的每个项目分配值 我有以下代码 JComboBox jc1 new JComboBox jc1 addItem a jc1 addItem b jc1 addItem
  • JSON:TypeError:Decimal('34.3')不是JSON可序列化的[重复]

    这个问题在这里已经有答案了 我正在运行一个 SQL 查询 它返回一个小数列表 当我尝试将其转换为 JSON 时 出现类型错误 查询 res db execute SELECT CAST SUM r SalesVolume 1000 0 AS

随机推荐

  • LINQ 选择项的 Lambda 表达式

    我有这个代码 var list db Projects Where item gt item Loc IN Select p gt new id p Id title p Title pc p PostalCode 项目表有很多列 我需要动
  • 如何将索引像素格式图像转换为 32 位图像?

    我获取了一个图像并尝试使用 Graphics FromImage image 加载到图形对象中 但是如果图像具有索引像素格式 则会引发异常 有没有办法安全地转换索引图像 Update 感谢 Joe 提供的提示 将旧图像绘制在新图像上 而不是
  • 如何将 gsutil 与多个帐户一起使用?

    我经常使用至少两个帐户的 Google Cloud Storage 电子邮件受保护 cdn cgi l email protection and 电子邮件受保护 cdn cgi l email protection 我用了gsutil co
  • 如何从打字稿访问垫菜单触发器

    我有以下 html
  • 如何以编程方式打开 Android Q 中的“设置”面板?

    As per 安卓Q新功能 有一个内联设置面板显示关键连接设置 使用户可以修改不同的连接设置 例如飞行模式 wifi 音量 NFC 和互联网连接 我怎样才能打开它以编程方式设置面板从我的应用程序 就像下面的屏幕截图一样 使用 Android
  • sum 函数如何在 python 中与 for 循环一起工作[重复]

    这个问题在这里已经有答案了 我在python中使用sum函数 我很清楚它的一般结构sum 可迭代 开始 但我无法理解以下代码背后的逻辑 test sum 5 for i in range 5 print output test 输出 25
  • Android:addTextChangedListener 无法正常工作

    我想对用户在其中输入的内容做出反应EditText所以我用了addTextChangedListener方法 当用户输入单个字符时 代码为onTextChanged正在运行 一切正常 例如 如果用户输入 a 那么onTextChanged将
  • ggplot2 以轴单位指定点大小

    我想从一个简单的数据集中绘制一个矩形内有大点的图 我想在不同方面显示可能有多个结果 问题是矩形的大小 使用geom rect 以轴单位定义 而size的论证geom point是在其他一些单位 因此 矩形上的点的相对大小根据面的数量而变化
  • 浏览器后退按钮处理

    我正在尝试处理浏览器后退按钮事件 但找不到任何解决方案 我想询问用户是否使用 确认框 单击浏览器后退按钮 如果他选择 确定 我必须允许后退按钮操作 否则我必须停止后退按钮操作 任何人都可以帮助我实现这一点 如果按下后退按钮 则警告 确认用户
  • 在 XElement.Load 上保留 \r\n

    有没有办法可以在 XElement Load 上保留 r n TextReader reader new StringReader rawInputString rawInputString is just text in html for
  • 关于清单中的全屏和无标题栏

    我想将我的应用程序设置为全屏视图 我想到将其设置在个人活动中使用FullScreen and NoTitlebar 但我想在整个应用程序的清单 XML 文件中设置它 而不是每个活动 这可能吗 帮助我 谢谢 要将您的应用程序或任何单独的活动显
  • 如何通过单击 ASP.NET 中的图像按钮来传输 zip 文件?

    我的问题 当用户单击 aspx 页面上的图像按钮时 代码隐藏会创建一个 zip 文件 然后我尝试将该 zip 文件流式传输给用户 为了流式传输文件 我使用以下代码 FileInfo toDownload new FileInfo fullF
  • C# 8 switch 表达式不够“智能”

    这段代码很简单 只是一个普通的开关 bool isSomething strSomething switch I gt true D gt false gt null 但是 编译器给了我以下错误 CS0037 无法将 null 转换为 bo
  • python中的嵌套正则表达式

    在 Perl 中我可以这样做 number qr zero one two three four five six seven eight nine ix foo qr quantity s number ix 我的实际正则表达式有很多行
  • 如何在浏览器中调试angularjs的$rootScope对象

    当 AngularJS 应用程序加载到浏览器中时 有没有办法对其进行调试 IE 我希望得到 rootScope我当前的应用程序 我该怎么做呢 巴塔朗 1 另外 您可以通过从控制台执行以下命令来获取 DOM 中任何元素的范围 angular
  • 根据列表框尺寸调整列表框内容的大小

    我正在尝试根据列表框本身调整列表框内容的大小 这是在 WPF 中完成的 关于这如何可能的任何想法 我认为当您说 调整大小 时 您的意思是您想要在两个方向上拉伸项目 要采用默认的列表框并水平拉伸项目 您需要做的是
  • C++ 求两个向量之间的差异

    假设你有 2 个向量 vector
  • 如何在 Eclipse 中找到可重写的方法

    public class test2 extends ListActivity 例如 我想找到 ListActivity 中可以重写的方法是什么 在 eclipse 中找到这个的快捷键是什么 如何通过 eclipse intellisens
  • 如何将 fancybox 绑定到动态添加的元素?

    我使用 jquery fancybox 1 3 4 作为弹出表单 但我发现 fancybox 无法绑定到动态添加的元素 例如 当我向当前文档添加 html 元素时 像这样 首先我使用 jquery 将一个元素附加到主体 document b
  • Jackson - 将内部对象列表反序列化为更高级别的列表

    使用 Spring Boot 和 Jackson 如何将包装 内部列表直接反序列化为外层列表 例如 我有 transaction items item itemNumber 193487654 itemDescription Widget