Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Jackson将可变(原语/对象)JSON属性反序列化为对象_Java_Json_Jackson_Deserialization - Fatal编程技术网

Java 使用Jackson将可变(原语/对象)JSON属性反序列化为对象

Java 使用Jackson将可变(原语/对象)JSON属性反序列化为对象,java,json,jackson,deserialization,Java,Json,Jackson,Deserialization,给定一个JSON对象,该对象具有可变属性(例如标签),可以是原语值(例如字符串)或对象。假设的用例可以是标签多重翻译的包装器: { "label": "User name" } 或 目标是使反序列化始终在Java端返回一个固定的结构。因此,如果给定一个原语值,它总是转换为目标POJO的某个属性(例如,其他),即: public class Translations { @JsonDeserialize(using = PluralizedTranslationDeserialize

给定一个JSON对象,该对象具有可变属性(例如标签),可以是原语值(例如字符串)或对象。假设的用例可以是标签多重翻译的包装器:

{
   "label": "User name"
}

目标是使反序列化始终在Java端返回一个固定的结构。因此,如果给定一个原语值,它总是转换为目标POJO的某个属性(例如,其他),即:

public class Translations {
   @JsonDeserialize(using = PluralizedTranslationDeserializer.class)
   public PluralizedTranslation label;
}

public class PluralizedTranslation {
   public String one;
   public String other;  // used as default fields for primitive value
}
目前,通过使用检查属性是否为原始属性的自定义项来解决此问题:

public class PluralizedTranslationDeserializer extends JsonDeserializer {
    @Override
    public PluralizedTranslation deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        ObjectCodec oc = jsonParser.getCodec();
        JsonNode node = oc.readTree(jsonParser);
        PluralizedTranslation translation;

        if (node.isTextual()) {
            translation = new PluralizedTranslation();
            translation.other = node.asText();
        } else {
            translation = oc.treeToValue(node, PluralizedTranslation.class);
        }

        return translation;
    }
}

有没有一种更优雅的方法来处理可变的JSON属性,而不需要在节点级运行的解码器?

您可以使
标签设置器更通用,并添加一些处理这两种情况的逻辑

public class Translations {
    // Fields omitted.

    @JsonProperty("label")
    public void setLabel(Object o) {
        if (o instanceof String) {
            // Handle the first case
        } else if (o instanceof Map) {
            // Handle the second case
        } else {
            throw new RuntimeException("Unsupported");
        }
    }
}
替代解决方案,它将工厂方法放在
多重翻译
类中,使
翻译
类不受影响:

public class PluralizedTranslation {
    public String one;
    public String other;  // used as default fields for primitive value

    @JsonCreator
    private PluralizedTranslation(Object obj) {
        if (obj instanceof Map) {
            Map map = (Map) obj;
            one = (String) map.get("one");
            other = (String) map.get("other");
        } else if (obj instanceof String) {
            other = (String) obj;
        } else {
            throw new RuntimeException("Unsupported");
        }
    }
} 

请注意,构造函数可以标记为
private
,以防止意外使用。

这个问题与可变性无关。您只是有一个属性,并希望以某种方式对其进行反序列化。@Miha_x64我将属性值描述为可变的,因为其值的类型是可变的。很抱歉让人误解这个形容词,这个问题当然不是关于(Java)对象的可变性。谢谢你的回答。实际上,此解决方案消除了
JsonDeserializer
。不幸的是,它还将
pluralizedtransation
创建逻辑移到了POJO中。因此,它将获得对某些工厂和/或
ObjectMapper
的依赖关系,而这些工厂和/或对象映射器实际上并不漂亮。此外,对于
私有
字段(为了简单起见,在问题中省略了这些字段),我们需要为
添加额外的检查,以进行实例多重翻译
。总的来说,这个替代方案在我看来并不干净……@dim:我不能完全理解你的反对意见,但我会尽力回答。在任何情况下都需要某种工厂。我认为,把它放在课堂上会更容易理解发生了什么。我不明白需要一个多重翻译的
o实例。在这两种情况下,都会创建一个
多重翻译的实例,因此这将是该类用户唯一需要处理的事情。我正在添加我提出的另一种方法,它将多重翻译的创建放在一个私有构造函数中,我觉得这相当优雅。我同意你的解决方案是可以理解的。我的第一个反对意见与这样一个事实有关,即
setLabel
应该能够接受
pluralizedtransation
的有效实例(这目前会导致
运行时异常
),但这是一个很简单的问题。第二:使用
ObjectMapper
而不是手工制作的映射是合理的,这意味着必须将其注入POJO。这是我不舒服的地方。然而,您的建议对于给定的简单情况是有效的,但我更多的是搜索magic
@JsonDefaultValue
annotation;)。
public class PluralizedTranslation {
    public String one;
    public String other;  // used as default fields for primitive value

    @JsonCreator
    private PluralizedTranslation(Object obj) {
        if (obj instanceof Map) {
            Map map = (Map) obj;
            one = (String) map.get("one");
            other = (String) map.get("other");
        } else if (obj instanceof String) {
            other = (String) obj;
        } else {
            throw new RuntimeException("Unsupported");
        }
    }
}