给定具有可变属性的JSON对象(例如 label ),其可以是原始值(例如字符串)或对象。假设用例可以是标签复数翻译的包装器:
{
"label": "User name"
}
或
{
"label": {
"one": "A label",
"other": "The labels"
}
}
目标是使Jackson反序列化始终在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
}
目前,通过使用自定义JsonDeserializer
来解决问题,该自定义Apache Lucene检查属性是否为原始属性:
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属性而无需在节点级别上运行的解码器?
答案 0 :(得分:2)
您可以使label
setter更通用,并添加一些处理这两种情况的逻辑。
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");
}
}
}
替代解决方案,它将工厂方法放在PluralizedTranslation
类中,使Translations
类不受影响:
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
以防止意外使用。