如何在 Jackson 中将原始 json 字符串注入到字段中?
Posted
技术标签:
【中文标题】如何在 Jackson 中将原始 json 字符串注入到字段中?【英文标题】:How to express in Jackson injection of original json string into a field? 【发布时间】:2022-01-02 20:40:27 【问题描述】:有一个JSON字符串""" "a": 1, "b": "hello" """
。
我想创建一个模型,包含“a”、“b”和“originalJson”。
class MyModel
public int a;
public String b;
public String originalJson;
void test1()
var payload = """ "a": 1, "b": "hello" """;
// how to apply Jackson here?
MyModel model = magicParse(payload, MyModel.class);
assertEquals(1, model.a);
assertEquals("hello", model.b);
assertEquals(payload, model.originalJson);
如果我们将其扩展到更广泛的应用程序
void test2()
var payload = """ [
"a": 1, "b": "hello",
"a": 2, "b": "bye"
]
""";
// how to apply Jackson here?
MyModel[] models = magicParse(payload, MyModel[].class);
var firstModel = model[0]
assertEquals(1, firstModel.a);
assertEquals("hello", firstModel.b);
assertEquals(""""a": 1, "b": "hello"""", firstModel.originalJson);
var secondModel = model[2]
assertEquals(2, secondModel.a);
assertEquals("bye", secondModel.b);
assertEquals(""""a": 2, "b": "bye"""", secondModel.originalJson);
在 Jackson 中是否有一种自然的方法(注释、配置等)?
【问题讨论】:
我会说你唯一的选择是使用自定义反序列化器。 【参考方案1】:你可以使用ObjectMapper.readTree()
:
private static final ObjectMapper MAPPER = new ObjectMapper();
public MyModel magicParse(String payload)
throws JsonMappingException, JsonProcessingException
JsonNode root = MAPPER.readTree(payload);
int a = root.get("a").asInt();
String b = root.get("b").asText();
return new MyModel(a, b, payload);
您还需要 MyModel
的构造函数(或根据您的情况设置设置器):
public class MyModel
public int a;
public String b;
public String originalJson;
MyModel(int a, String b, String originalJson)
this.a = a;
this.b = b;
this.originalJson = originalJson;
【讨论】:
【参考方案2】:使用自定义反序列化器尝试了几种解决方案,但看起来它们需要大量代码来模糊主要意图。我看到的基本问题是,在反序列化器中,我们可以访问JsonParser
,它是有状态的并维护“一次性”算法,因此无法在不干扰正常解析过程的情况下从中获取 JSON 子树/子字符串。
另一种方法更具可读性,尽管我们对有效负载进行两次反序列化可能会对性能产生影响。
想法是获取JsonNode
并使用它反序列化模型并进行进一步的转换:在基本反序列化之后和返回结果之前传递根节点。
// utility for mapping
public static <T, R> R readValue(
String json,
Class<T> clazz,
BiFunction<T, JsonNode, R> transformValue
)
JsonNode node = getObjectMapper().readValue(json, JsonNode.class);
T value = mapper.treeToValue(node, clazz);
return transformValue.apply(value, node);
// concrete usage
MyModel getModel(String payload)
return readValue(
payload,
MyModel.class,
(m, node) ->
m.payload = node.toString();
return m;
);
【讨论】:
以上是关于如何在 Jackson 中将原始 json 字符串注入到字段中?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Jackson 将原始 JSON 反序列化为 Java 对象
如何在 Jackson 中将对象序列化为 ObjectNode 的值?