【问题标题】:Jackson: is it possible to include property of parent object into nested object?Jackson:是否可以将父对象的属性包含到嵌套对象中?
【发布时间】:2013-10-04 21:38:50
【问题描述】:

我正在使用 Jackson 来序列化/反序列化 JSON 对象。

我有一个Study 对象的以下 JSON:

{
    "studyId": 324,
    "patientId": 12,
    "patient": {
        "name": "John",
        "lastName": "Doe"
    }
}

更新:很遗憾,无法修改 JSON 结构。这是问题的一部分。

我想将对象反序列化为以下类:

public class Study {
    Integer studyId;
    Patient patient;
}

public class Patient {
    Integer patientId;
    String name;
    String lastName;
}

是否可以在Patient 对象中包含patientId 属性?

我能够将patient 对象反序列化为Patient 类(具有相应的namelastName 属性),但无法包含patientId 属性。

有什么想法吗?

【问题讨论】:

  • 我真的不知道杰克逊是否会喜欢这个,但你可以尝试将Patient 作为Study 中的内部类并将getPatientId() 实现为return Study.this.patientId 以使似乎数据首先应该属于它。 (不。如果我不需要,我不会这样做。)

标签: json jackson deserialization


【解决方案1】:

您可以为您的用例使用自定义反序列化程序。这是它的样子:

import java.io.IOException;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;

public class StudyDeserializer extends JsonDeserializer<Study>
{
    @Override
    public Study deserialize(JsonParser parser, DeserializationContext context)
        throws IOException, JsonProcessingException
    {
        JsonNode studyNode = parser.readValueAsTree();

        Study study = new Study();
        study.setStudyId(studyNode.get("studyId").asInt());

        Patient patient = new Patient();
        JsonNode patientNode = studyNode.get("patient");
        patient.setPatientId(studyNode.get("patientId").asInt());
        patient.setName(patientNode.get("name").asText());
        patient.setLastName(patientNode.get("lastName").asText());
        study.setPatient(patient);

        return study;
    }
}

Study 类中将上述类指定为您的反序列化器:

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;

@JsonDeserialize(using = StudyDeserializer.class)
public class Study
{
    Integer studyId;
    Patient patient;

    // Getters and setters
}

现在,您指定的 JSON 输入应该会按预期反序列化。

【讨论】:

  • 由于代码中使用了硬编码的字段名称,它很快就会中断。添加(或删除)新字段 - 更改,字段名称使用蛇形大小写 - 更改。 :( 应该有一些声明的方式。
【解决方案2】:

没有声明的方式来做这样的对象转换:你在 JSON 和 POJO 之间转换结构。 Jackson 在这方面的支持受到设计的限制:有两件事超出了范围:验证(使用外部验证;Bean Validation API 或 JSON Schema 验证器)和转换(可以使用 JsonNode 或外部库)。

【讨论】:

    【解决方案3】:

    根据这种格式的稳定性(以及您的 QA 人员的心情),您可以在将 Json 传递给 Jackson 之前直接对其进行更改。这将修复损坏的东西。 正则表达式是一个想法。在 Hashmap 中读取它,将值移动到那里并将其作为另一个固定的 Json 写出来。但在伪代码中更简单:

    String json = "...";
    String lines = json.split( "\r" );
    swap( lines[2], lines[3] ); //*1
    String fixed = join( lines ); //*2
    

    在哪里

    *1: tmp = lines[2]; lines[2] = lines[3]; lines[3] = tmp;
    *2: http://stackoverflow.com/questions/1515437/java-function-for-arrays-like-phps-join
    

    (如果我必须走这条路,我会使用 hashmap 方法)

    【讨论】:

    • JSON 结构来自外部,无法修改。检查问题的更新。
    • 是的,你写的。这个答案是关于修改它在你得到它之后。是的,这很丑陋,但取决于您的项目的性质。
    【解决方案4】:

    您的患者 ID 存储在患者对象之外。把它放进去,一切都是闪亮的;)

    如果你坚持把它放在 json 中,恐怕你有麻烦了。 (最好是说服 Json 设计器将它存储在 Patient 对象中它所属的位置,就像在 Java 中一样。)

    如果没有任何帮助,您必须使用数据传输对象 (https://en.wikipedia.org/wiki/Data_transfer_object) 或自定义反序列化器 (Setting up JSON custom deserializer) 才能在理智和疯狂的表示之间进行转换。

    【讨论】:

    • 不幸的是,更改源 JSON 不是一种选择。 patientId 将存储在 patient 对象之外。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-11
    • 2019-07-22
    • 1970-01-01
    • 1970-01-01
    • 2011-12-21
    • 2021-06-09
    相关资源
    最近更新 更多