【问题标题】:Parse JSON array with jackson where objects are strings?用杰克逊解析JSON数组,其中对象是字符串?
【发布时间】:2012-06-11 23:59:50
【问题描述】:

我有一个有点奇怪的问题。我创建了一个对象,我们称之为 Profile,它通过我调用的 API 成功解析单个 JSON 对象。还有一个多配置文件接口,它将返回配置文件对象的 JSON 数组。问题是,多配置文件接口将子对象转换为字符串。有没有一种自动方法可以告诉杰克逊将这些解析为对象?

单个对象的示例: { "foo": "bar" }

多对象示例: [ "{ \"foo\": \"bar\" }", "{ \"blah\": \"ugh\" }" ]

(抱歉不能使用真实数据)

请注意,子对象实际上是字符串,其中包含转义引号。

为了完整起见,我的多对象解析代码如下所示:

ObjectMapper mapper = new ObjectMapper();
Profile[] profile_array = mapper.readValue(response.content, Profile[].class);
for (Profile p: profile_array)
{
    String user = p.did;
    profiles.put(user, p);
}

正如我所说,在单配置文件的情况下,配置文件对象会解析。在多配置文件的情况下,我得到了这个异常:

Exception: org.codehaus.jackson.map.JsonMappingException: Can not construct instance of com.xyz.id.profile.Profile, problem: no suitable creator method found to deserialize from JSON String

【问题讨论】:

  • Profile 是类还是接口?为什么不在上面实现 fromValue(String) 并将解析逻辑放在那里?
  • Profile 是一个类,它是 JSON 配置文件对象数据的容器。

标签: java json jackson


【解决方案1】:

我想您必须创建一个自定义反序列化器并将其应用于该数组的每个元素。

class MyCustomDeserializer extends JsonDeserializer<Profile> {
    private static ObjectMapper om = new ObjectMapper();

    @Override
    public Profile deserialize(JsonParser jp, DeserializationContext ctxt) {
        // this method is responsible for changing a single text node:
        // "{ \"foo\": \"bar\" }"
        // Into a Profile object

        return om.readValue(jp.getText(), Profile.class);
    }
}

【讨论】:

  • 我担心这就是答案。我试试看,谢谢。
【解决方案2】:

对于嵌入的 JSON-in-JSON 内容的“重新解析”没有开箱即用的支持。 但这听起来像是一个可能的增强请求 (RFE)...

【讨论】:

    【解决方案3】:

    您是否尝试过使用 JAXB?

                final ObjectMapper mapper = new ObjectMapper();
    
                // Setting up support of JAXB
                final AnnotationIntrospector introspector = new JaxbAnnotationIntrospector();
    
                // make deserializer use JAXB annotations (only)
                mapper.getDeserializationConfig().setAnnotationIntrospector(
                        introspector);
    
                // make serializer use JAXB annotations (only)
                mapper.getSerializationConfig().setAnnotationIntrospector(
                        introspector);
    
                final StringReader stringReader = new StringReader(response);
                respGetClasses = mapper.readValue(stringReader,
                        FooBarClass.class);
    

    以上内容应该可以帮助您入门...

    另外,您需要像这样标记每个子类:

    @XmlElement(name = "event")
    public List<Event> getEvents()
    {
        return this.events;
    }
    

    【讨论】:

    • 虽然可以通过这种方式使用 JAXB 注释,但这对解决手头的实际问题有何帮助?
    • @StaxMan 他的问题是他想强制将 JSON 解析为复杂的对象并且他遇到了问题。我只是提出我的解决方案(使用 JAXB),因为我在使用 Jackson 库时用它来解决像他这样的问题......
    • 其实我不认为他的问题真的是:如果你仔细看看他展示的 JSON 样本,多对象的情况,内容是一个字符串而不是 JSON 的更大问题.但即使是 JSON,数组和对象之间也会存在结构差异。这就是我问的原因:您正在展示如何指定属性名称,这可能很有用,但它似乎并不是提交者正在努力解决的问题。所以我想也许我在这里遗漏了一些东西......
    • @StaxMan - 啊哈,我的错。尽管他在问如何防止它们变成字符串,但我的解决方案会有所帮助。基本上他有普通的 JSON,一旦他通过他的“多配置文件接口”传递它,它们就会作为字符串而不是对象返回。我正在解决这个问题,以修复他的“多配置文件界面”,而不是将字符串解析为对象。但也许我没有正确理解 OP,它以前发生过,它会再次发生! :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-25
    • 2014-03-05
    • 1970-01-01
    • 2019-07-27
    • 1970-01-01
    相关资源
    最近更新 更多