ContextualDeserializer,用于使用 Jackson 将 JSON 映射到不同类型的映射

2023-12-07

此 JSON 片段应映射到包含以下内容的 Java 对象:cars类型字段Map<String, Car> and a bikes类型字段Map<String, Bike>。因为自行车和汽车可以是 JSON 文件中的空字符串,所以我需要一个自定义反序列化器(看到这个问题).

{
    "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"
        }
    },
    "bikes" : {
        "Bike 1" : {
            "color" : "black"
        },
        "Bike 2" : {
            "color" : "red"
        }
    }
}

我考虑过拥有一个通用的自定义反序列化器的实例,可以由createContextual(DeserializationConfig cfg, BeanProperty property)的方法ContextualDeserializer基于 BeanProperty 参数。通用的自定义解串器如下所示:

public class MapsGenericDeserializer<T> extends
        JsonDeserializer<Map<String, T>> {

    private ObjectMapper mapper; // ObjectMapper without special map deserializer

    public MapsGenericDeserializer(ObjectMapper mapper) {
        this.mapper = mapper;
    }

    @Override
    public Map<String, T> deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        ObjectCodec codec = jp.getCodec();
        JsonNode node = codec.readTree(jp);
        if (!"".equals(node.getTextValue())) {
            return mapper.readValue(node, 
                    new TypeReference<Map<String, T>>() {});
        }
        return null; // Node was an empty string
    }
}

下面的上下文序列化器不起作用,因为从MapsGenericDeserializer<Car> to JsonDeserializer<Map<String,?>>不可能。也许这在较新版本的 Java 中是可能的,但它不适用于我正在编码的 Android 版本。那么我怎样才能实现所需的行为呢?

public class MapsDeserializer extends JsonDeserializer<Map<String, ?>>
        implements ContextualDeserializer<Map<String, ?>> {

    private ObjectMapper mapper;

    MapsGenericDeserializer<Car> carDeserializer = new MapsGenericDeserializer<Car>(mapper);
    MapsGenericDeserializer<Bike> bikeDeserializer = new MapsGenericDeserializer<Bike>(mapper);

    public MapsDeserializer(ObjectMapper mapper) {
        this.mapper = mapper;
    }

    @Override
    public JsonDeserializer<Map<String, ?>> createContextual(DeserializationConfig cfg,
            BeanProperty property) throws JsonMappingException {

        Class<?> targetClass = property.getType().containedType(1).getRawClass();

        if(targetClass.equals(Car.class) { 
            return carDeserializer; // Type mismatch!
        } else if (targetClass.equals(Bike.class)) {
            return bikeDeserializer; // Type mismatch!
        } else {
            return this;
        }
    }

    // ...
}

这是我可能采取的方法。

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.Version;
import org.codehaus.jackson.map.BeanProperty;
import org.codehaus.jackson.map.ContextualDeserializer;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.JsonDeserializer;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.module.SimpleModule;

public class Foo
{
  public static void main(String[] args) throws Exception
  {
    EmptyStringAsMapDeserializer<Map<String, ?>> emptyStringAsMapDeserializer = 
        new EmptyStringAsMapDeserializer<Map<String, ?>>(null, new ObjectMapper());

    SimpleModule module = new SimpleModule("ThingsDeserializer", Version.unknownVersion());
    module.addDeserializer(Map.class, emptyStringAsMapDeserializer);

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

    Person person = mapper.readValue(new File("input.json"), Person.class);
    System.out.println(mapper.writeValueAsString(person));
  }
}

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

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

class Bike
{
  public String color;
}

class EmptyStringAsMapDeserializer<T>
    extends JsonDeserializer<Map<String, ?>>
    implements ContextualDeserializer<Map<String, ?>>
{
  private Class<?> targetType;
  private ObjectMapper mapper;

  EmptyStringAsMapDeserializer(Class<?> targetType, ObjectMapper mapper)
  {
    this.targetType = targetType;
    this.mapper = mapper;
  }

  @Override
  public JsonDeserializer<Map<String, ?>> createContextual(DeserializationConfig config, BeanProperty property)
      throws JsonMappingException
  {
    return new EmptyStringAsMapDeserializer<Object>(property.getType().containedType(1).getRawClass(), mapper);
  }

  @Override
  public Map<String, ?> deserialize(JsonParser jp, DeserializationContext ctxt)
      throws IOException, JsonProcessingException
  {
    JsonNode node = jp.readValueAsTree();
    if ("".equals(node.getTextValue()))
      return new HashMap<String, Object>();
    ObjectMapper mapper = new ObjectMapper();
    return mapper.readValue(node, mapper.getTypeFactory().constructMapType(Map.class, String.class, targetType));
  }
}

泛型类型参数可能有点乱。我做了一些快速复制粘贴。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ContextualDeserializer,用于使用 Jackson 将 JSON 映射到不同类型的映射 的相关文章

  • 如何循环遍历 JSON 数组?

    我有一些 JSON 代码 其中包含多个对象 MNGR NAME Mark MGR ID M44 EMP ID 1849 MNGR NAME Steve PROJ ID 88421 PROJ NAME ABC PROJ ALLOC NO 49
  • 如何查看 org.codehaus.jackson 日志消息 - 使用logging.properties

    我正在尝试反序列化传入的PUT使用 JSON 请求正文进行请求org codehaus jackson包裹 我收到错误消息The request sent by the client was syntactically incorrect
  • 如何在保留矩阵维度的同时序列化 numpy 数组?

    numpy array tostring似乎没有保留有关矩阵维度的信息 请参阅这个问题 https stackoverflow com q 30697769 1156707 要求用户发出调用numpy array reshape 有没有办法
  • 从通用对象访问字段变量

    我有两节课ClassOne and ClassTwo 更新公共字段data i e public class ClassOne public byte data new byte 10 Thread that updates data an
  • 改造2:使用json对象发送文件

    我在请求正文中发送对象 如下所示 title test description test images POST create data Call
  • JSON.stringify 对于大型对象来说非常慢

    我在 javascript 中有一个非常大的对象 大约 10MB 当我对其进行字符串化时 需要很长时间 因此我将其发送到后端并将其解析为一个对象 实际上是带有数组的嵌套对象 这也需要很长时间 但这不是我们在这个问题中的问题 问题 我怎样才能
  • JSON 从子对象获取父对象

    我怎样才能得到discount值如果品牌id 983 示例 JSON prods info rate 100 grocery brand A brand id 983 brand B
  • Twitter api 文本字段值被截断

    为什么文本字段值被截断以及如何获得完整的值 截至目前 我正在尝试获取如下所示的文本字段值 do if let responseObject try NSJSONSerialization JSONObjectWithData respons
  • 将 JSON URL 转换为 R 数据帧

    我在将 JSON 文件 从 API 转换为 R 中的数据帧时遇到问题 例如 URL 我尝试了 S O 的一些不同建议 包括将json数据转换为R中的数据框 https stackoverflow com questions 28683769
  • 如何在 Angular 2 karma jasmine 测试中从 JSON 文件加载模拟数据?

    我在写信业力茉莉花测试用例角2 我们遇到了在单独的 JSON 文件中模拟数据的需求 因为数据很大 希望确保代码整洁 为此我进行了很多搜索但没有找到合适的解决方案 我们已经使用以下方式模拟 HTTP 服务模拟后端 所以我们不能使用Angula
  • 数组与列表的性能

    假设您需要一个需要频繁迭代的整数列表 数组 我的意思是非常频繁 原因可能有所不同 但可以说它位于大容量处理的最内层循环的核心 一般来说 人们会选择使用列表 List 因为它们的大小具有灵活性 最重要的是 msdn 文档声称列表在内部使用数组
  • 我可以避免使用泛型来避免急于解决特征实现的歧义吗?

    考虑以下 Rust 代码 use std collections HashMap use std hash Hash trait Foo
  • 指示泛型返回动态类型的对象

    这个问题是我原来问题的后续问题here https stackoverflow com questions 2541184 using a type object to create a generic 假设我有以下泛型类 简化 class
  • 在 Django 模板中通过键访问字典

    我正在将字典从我的视图传递到模板 所以 key1 value1 key2 value2 传入并循环键 值对很好 但是我还没有找到从特定键直接在视图中访问的优雅解决方案 例如 key1 例如 bu json items key1 我可以使用一
  • 如何为 cxf jax-rs 2.0 客户端注册 jackson json 提供程序?

    我有一个 JAX RS 客户端正在发出一个简单的 GET 请求 我使用 CXF 实现和 Spring 进行 DI 呼叫成功 我收到响应代码 200 但是在将响应读入 POJO 时出现错误 例外 2015 05 08 16 11 55 457
  • 解析“流”JSON

    我在浏览器中有一个网格 我想通过 JSON 将数据行发送到网格 但浏览器应该在接收到 JSON 时不断解析它 并在解析时将行添加到网格中 换句话说 在接收到整个 JSON 对象后 不应将行全部添加到网格中 应该在接收到行时将其添加到网格中
  • C# 抽象泛型方法

    C net 3 5 我正在尝试创建一个具有通用方法的基类 从它继承的类应该指定方法的类型 这样做的前提是创建管理过滤的类 所以我有 public abstract class FilterBase NEED Help Declaring t
  • 将 MOXy 设置为 JAXB 提供程序,而在同一包中没有属性文件

    我正在尝试使用 MOXy 作为我的 JAXB 提供程序 以便将内容编组 解组到 XML JSON 中 我创建了 jaxb properties 文件 内容如下 javax xml bind context factory org eclip
  • 在 Android 应用程序资源中使用 JSON 文件

    假设我的应用程序的原始资源文件夹中有一个包含 JSON 内容的文件 我如何将其读入应用程序 以便我可以解析 JSON See 开放原始资源 http developer android com reference android conte
  • JSON:TypeError:Decimal('34.3')不是JSON可序列化的[重复]

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

随机推荐

  • 静态函数与静态成员函数 C++ [重复]

    这个问题在这里已经有答案了 我一直在阅读一些有关静态函数和静态成员函数的内容 根据我的理解 如果function被声明为静态 那么该函数仅对其翻译单元可见 而对其他地方不可见 静态的成员函数相反 它是一个无需实例化其类的任何对象即可调用的函
  • MYSQL安装问题[关闭]

    Closed 这个问题是无关 目前不接受答案 在我的 Mac 上通过终端升级了一些 gems 后 我创建了一个由 mysql 数据库支持的新的 Rails 项目 启动应用程序后 会出现常规的欢迎页面 问题是 我尝试单击标题为 关于您的应用程
  • 如何用Python进行二维回归分析?

    首先 我对Python不熟悉 对Python代码的机制还勉强了解 但我需要通过Python做一些统计分析 我尝试了很多很多方法来弄清楚但我失败了 基本上 我有 3 个数据数组 假设这些数组是X Y Z 我做了一些分析 X Y and Z Y
  • 类型错误:无法腌制 PyCapsule 对象

    I use dill将 ML 模型保存到文件 当我运行测试时python m unittest有用 但是如果我尝试运行测试python setup py test它出现错误TypeError can t pickle PyCapsule o
  • 为什么结构化绑定引入变量作为值,而不是引用?

    我正在学习结构化绑定声明 我的理解是在auto x y expr 变量x and y引入了类型 引用std tuple element
  • Django:在事件发生后将帖子离线

    我正试图在某个活动 某个确定的日期 之后将帖子下线 我开发了一个简单的模型来测试我的目标 并在模型中放置了一个函数 命名为 is expired 理想情况下 必须定义帖子是否在线 下面有model from django db import
  • Android 中每秒都会触发 Intent 吗?

    我正在寻找每秒广播的意图 我调查了android intent action TIME TICK但这种意图每分钟都会广播 我知道 AlarmManger handler thread 可以用于此目的 但我倾向于使用系统广播意图 请分享您的想
  • 如何向 MAUI 中的 UI 元素添加上下文菜单?

    下面的代码不起作用 错误 XLS0415 在类型 Grid 中找不到可附加属性 ContextActions 并且 未找到类型 FlyoutBase
  • 大文件复制期间的进度(复制项目和写入进度?)

    有没有办法在 PowerShell 中复制一个非常大的文件 从一台服务器到另一台服务器 并显示其进度 有一些解决方案可以将 Write Progress 与循环结合使用来复制许多文件并显示进度 但是我似乎找不到任何可以显示单个文件进度的内容
  • 子进程给出错误。 “该系统找不到指定的文件”

    这是我的代码 import urllib import requests from bs4 import from subprocess import Popen PIPE import os connectString SYSTEM me
  • 更改mysql查询ORDER BY中的时间格式

    我正在开发一个项目 其中用户拥有以正常格式存储日期的数据库2013 年 3 月 8 日我想用日期对输出进行排序 但没有得到正确的输出 bcos 未使用时间戳 那么有什么方法可以在 mysql 查询中使用或将该日期字段转换为时间戳 SELEC
  • 如何以编程方式操作“开始”菜单的“最近使用的程序”列表? [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 我正在寻找一种使程序显示 经常 使用的方法 以便它们出现在 开始 菜单的 最近使
  • 来自 JavaScript 的 HTTP 请求使用包含标头的原始消息

    我知道如何使用 jQuery 或 XMLHttpRequest 从 javascript 向我的 REST api 发出 HTTP 请求 我现在想做的是发出请求而不设置标头值的属性 一个HTTP请求消息由组成 请求行 例如 GET imag
  • 避免 Pylint 警告 E1101:对于具有动态属性的类,“.. 的实例没有 .. 成员”

    想象一个函数动态地使用以下方法向对象添加属性setattr 这样做的原因是我想将一些外部结构 例如给定的参数树 映射到一个对象 my object SomeClass apply structure my object some descr
  • 在java中绘制极坐标图

    有谁知道我如何开始在java中绘制极坐标图并在该图上绘制一些点 我的意思是圆和线 我希望用 swing 之类的东西来做到这一点 而不是使用像 Jfreechart 这样的任何库 谢谢 您可能想看看利萨如曲线 的一个例子a 5 b 4 5 4
  • React/Redux useEffect 多次触发调度[重复]

    这个问题在这里已经有答案了 我在使用 useEffect 和dispatch 操作时遇到问题 我正在使用最新版本的react 18 1 0 基本上 我有以下在简单的代码中定义的代码 const Item gt const dispatch
  • 具有不等宽度项目的散景响应行

    我正在尝试在 bokeh 0 12 3 中创建一个响应行 其中包含一个图形和一个小部件框 其中小部件框的宽度比图形小得多 我只能通过以下方式实现前者 from bokeh io import output file show from bo
  • Meteor 中的后台任务

    我想知道 有什么办法可以实现后台任务吗 也许有工人池 你能给我指明方向吗 我正在考虑为此编写软件包 2019年更新 在考虑为任何内容编写包之前 首先查看是否有现有的包可以满足您的需要 在 Meteor 世界中 这意味着在 Atmospher
  • PlaceAutocompleteFragment 单击后消失

    我想实现 AutocompleteTextView 谷歌位置 但是当我单击片段中的 searchView 时 该片段消失了 掉落 My code Override protected void onCreate Bundle savedIn
  • ContextualDeserializer,用于使用 Jackson 将 JSON 映射到不同类型的映射

    此 JSON 片段应映射到包含以下内容的 Java 对象 cars类型字段Map