如何使用Jackson将JSON数组元素反序列化为原始JSON字符串值
Jackson 反序列化JSON数组为原始JSON字符串数组的实现方案
首先明确:你期望的能力可以实现,@JsonRawValue 本质是序列化阶段的注解,仅控制输出逻辑,本身不支持反序列化场景的原始值捕获,我们可以通过以下两种方案实现需求:
方案1:通用场景(不要求严格保留原始JSON的空格、换行)
该方案实现最简单,能满足绝大多数业务场景,也完全匹配你给出的测试用例断言要求:
- 先将整个JSON负载解析为Jackson的树模型
JsonNode - 遍历每个数组元素,直接调用
ObjectMapper的序列化方法将节点转回JSON字符串即可
对应修改后的测试代码如下:
void test() throws IOException { var payload = """ [ {"a": 1, "b": "hello"}, {"a": 2, "b": "bye"}, "something" ] """; ObjectMapper objectMapper = new ObjectMapper(); // 先解析为JsonNode数组 JsonNode rootNode = objectMapper.readTree(payload); String[] rawItems = new String[rootNode.size()]; for (int i = 0; i < rootNode.size(); i++) { // 将每个节点序列化为原始JSON字符串,自动保留对象、字符串等格式 rawItems[i] = objectMapper.writeValueAsString(rootNode.get(i)); } assertEquals("""{"a":1,"b":"hello"}""", rawItems[0]); assertEquals("""{"a":2,"b":"bye"}""", rawItems[1]); assertEquals("\"something\"", rawItems[2]); }
如果需要保留原JSON的缩进格式,可以给ObjectMapper配置SerializationFeature.INDENT_OUTPUT开启格式化输出即可。
方案2:严格保留原始输入的所有格式(空格、换行、属性顺序都不变)
如果要求截取的字符串和原输入完全一致,没有任何格式变化,可以通过Jackson的底层JsonParser接口实现,直接从原始输入中截取每个数组元素的字符范围:
void test() throws IOException { var payload = """ [ {"a": 1, "b": "hello"}, {"a": 2, "b": "bye"}, "something" ] """; List<String> rawItems = new ArrayList<>(); try (JsonParser parser = new ObjectMapper().getFactory().createParser(payload)) { // 跳过数组开始标记 if (parser.nextToken() == JsonToken.START_ARRAY) { char[] payloadChars = payload.toCharArray(); while (parser.nextToken() != JsonToken.END_ARRAY) { // 记录当前元素的起始、结束字符偏移量,直接从原字符串截取 int start = (int) parser.getCurrentLocation().getCharOffset(); parser.skipChildren(); int end = (int) parser.getCurrentLocation().getCharOffset(); rawItems.add(new String(payloadChars, start, end - start).trim()); } } } String[] result = rawItems.toArray(new String[0]); // 后续断言逻辑不变 }
内容的提问来源于stack exchange,提问作者diziaq
相关产品推荐
相关产品推荐

