解析json对象并获取原始子字符串

问题描述 投票:0回答:1

鉴于下面的 JSON,我目前有 Jackson 代码,它将把它解析成一个带有子对象数组的对象。 我可以轻松地将每个子对象序列化回字符串。

但是我发现很多极端情况,输出字符串与输入字符串不完全一样。 例如,输出字段顺序不一定与输入字段顺序匹配。 让我开始做这件事的极端情况是,我注意到如果我的子对象将“URL”字段声明为 URL,那么 "" 会转换为

null
,而不是
""
,因此输出为
 null
所以我的问题是,有没有办法让 Jackson 将字符串分解为代表子对象的子字符串,而不是将其解析为实际的 Java 对象?

{ "foo": "bar", "baz": [ { "index": 1, "url": "" }, { "url": "https://example.com", "index": 2 } ] }

换句话说,在上面的例子中,我想要的是一个有2个元素的List

{ "index": 1, "url": "" }

{ "url": "https://example.com", "index": 2 }

我疯了吗?  我需要编写一个自定义解串器吗?  我觉得杰克逊或多或少已经这样做了,我只是需要一种方法来实现它。

非常感谢。

编辑添加代码。

@JsonIgnoreProperties("foo") @Builder @Value @Jacksonized public static class Wrapper { List<SubObject> baz; } @Builder @Value @Jacksonized public static class SubObject { Integer index; URL url; } @Test public void runTest() throws IOException { ObjectMapper om = new ObjectMapper().registerModule(new VavrModule()); //for the Vavr List Wrapper wrapper = om.readValue(new File("src/test/resources/fixtures/WrapperFile.json"), Wrapper.class); List<SubObject> subObjects = wrapper.baz; List<String> subObjectStrings = subObjects.map(so -> safeWriteValueAsString(om, so)); subObjectStrings.forEach(s -> System.out.println(s)); }

产生这个输出

{"index":1,"url":null} {"index":2,"url":"https://example.com"}

请注意,这些都不是我想要的。

第二个子对象字符串的顺序错误。

第一个子对象的 URL 为 null 而不是“”。 虽然我可以通过将 URL 设为字符串而不是 URL 来处理 URL 问题,但这是一种可能的情况,而不是一般情况。

我想要的是类似于下面的内容(请注意,它无法编译。这是我正在寻找的东西,而不是我拥有的东西)。 我知道杰克逊必须能够读取字符串并决定子对象何时开始和结束。 应该可以获得子字符串和/或索引。 如果我有代表数组中每个对象的字符串,如果需要,我可以轻松使用 Jackson 将它们解析为实际的子对象。

// my theory of how it _could_ work @Test public void theoryTest() { ObjectMapper om = new ObjectMapper().registerModule(new VavrModule()); //for the Vavr List Map<String, String> propertyStrings = om.parseIntoPropertyStrings(f); String bazString = propertyStrings.getOrElse("baz", ""); List<String> bazEntryStrings = om.parseIntoArray(bazString); bazEntryStrings.forEach(s -> System.out.println(s);) }

	
jackson
1个回答
0
投票
p.getCodec().readTree(p).toString();

。 这样你就拥有了原始字符串,这就是我想要的,

并且
如果你愿意,你可以“正常”反序列化它。 lombok 注释只是一个样板去除器,它不会改变我正在解决的问题。

代码

import java.io.File; import java.io.IOException; import java.nio.file.Files; import org.testng.annotations.Test; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import io.vavr.collection.List; import io.vavr.collection.Map; import io.vavr.jackson.datatype.VavrModule; import lombok.Builder; import lombok.SneakyThrows; import lombok.Value; import lombok.extern.jackson.Jacksonized; import lombok.extern.slf4j.Slf4j; @Slf4j public class WrapperSubObjectTest { File f = new File("src/test/resources/fixtures/WrapperFile.json"); @Builder @Value @Jacksonized @JsonIgnoreProperties("foo") public static class Wrapper { List<SubObject> baz; } @Builder @Value @JsonDeserialize(using = SubObjectDeserializer.class) public static class SubObject { Integer index; String url; String originalString; } private static final ObjectMapper om = new ObjectMapper().registerModule(new VavrModule()); public static class SubObjectDeserializer extends StdDeserializer<SubObject> { public SubObjectDeserializer() { this(SubObject.class); } public SubObjectDeserializer(Class<?> vc) { super(vc); } @Override public SubObject deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { String s = p.getCodec().readTree(p).toString(); TypeReference<Map<String, String>> mapTR = new TypeReference<Map<String, String>>() {}; Map<String, String> map = om.readValue(s, mapTR); SubObject returnVal = new SubObject(Integer.parseInt(map.get("index").getOrElse("-1")) , map.get("url").getOrElse("https://badvalue.com"), s); return returnVal; } } @Test public void runTest() throws IOException { log.info("contents of file \n{}\n\nParsing results", Files.readString(f.toPath())); Wrapper wrapper = om.readValue(f, Wrapper.class); List<SubObject> subObjects = wrapper.baz; subObjects.forEach(so -> safeWriteValueAsString(om, so)); } @SneakyThrows private void safeWriteValueAsString(ObjectMapper om, SubObject so) { log.info("\noriginalString = {}\nparsed = {}", so.originalString, om.writeValueAsString(so)); } }

输出

contents of file { "foo": "bar", "baz": [ { "index": 1, "url": "" }, { "url": "https://example.com", "index": 2 } ] } Parsing results originalString = {"index":1,"url":""} parsed = {"index":1,"url":"","originalString":"{\"index\":1,\"url\":\"\"}"} originalString = {"url":"https://example.com","index":2} parsed = {"index":2,"url":"https://example.com","originalString":"{\"url\":\"https://example.com\",\"index\":2}"}

	
© www.soinside.com 2019 - 2024. All rights reserved.