如何在jackson json反序列化中跳过包装器对象

时间:2016-07-30 23:33:17

标签: android json jackson pojo jackson-dataformat-xml

我正在尝试使用jackson反序列化以下字符串。

{
  "roomName": "u8ec29p0j7q2m9f",
  "broadcastPresenceRoles": {
    "broadcastPresenceRole": [
      "moderator",
      "participant",
      "visitor"
    ]
  },
  "owners": {
    "owner": "anewuser@shahanshah"
  },
  "admins": {
    "admin": "sanjeet@shahanshah"
  },
  "members": null,
  "outcasts": {
    "outcast": [
      "sawan@shahanshah",
      "sus@shahanshah"
    ]
  },
  "ownerGroups": {
    "ownerGroup": "Friends"
  }
}

这是来自openfire rest apis的回应。 我遇到包装数组的包装器对象的问题。 在这里

"broadcastPresenceRoles": {
    "broadcastPresenceRole": [
      "moderator",
      "participant",
      "visitor"
    ]
  },

我尝试this打开容器,但没有取得成功。我不认为编写包装类是个好主意(因为我将不得不编写几个包装类)。我也需要通用解决方案,所以我可以将它与其他响应一起使用,因为apis在类似的包装对象格式中有其他响应。提前谢谢。

2 个答案:

答案 0 :(得分:4)

您可以在里面使用@JsonDeserialize创建自定义注释,并创建实现JsonDeserializer的自定义ContextualDeserializer。这个想法的灵感来自你提到的the solution,但是在json对象中展开任何一个属性更为通用。

以下是使用@JacksonAnnotationsInside的自定义注释,因为注释容器包含@JsonDeserialize

@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonDeserialize(using = JsonUnwrapPropertyDeserializer.class)
public @interface JsonUnwrapProperty {
}

以及实施JsonDeserializer的自定义ContextualDeserializer

public class JsonUnwrapPropertyDeserializer extends JsonDeserializer<Object> implements ContextualDeserializer {

    private JavaType unwrappedJavaType;
    private String unwrappedProperty;

    @Override
    public JsonDeserializer<?> createContextual(final DeserializationContext deserializationContext, final BeanProperty beanProperty) throws JsonMappingException {
        unwrappedProperty = beanProperty.getMember().getName();
        unwrappedJavaType = beanProperty.getType();
        return this;
    }

    @Override
    public Object deserialize(final JsonParser jsonParser, final DeserializationContext deserializationContext) throws IOException {
        final TreeNode targetObjectNode = jsonParser.readValueAsTree().get(unwrappedProperty);
        return jsonParser.getCodec().readValue(targetObjectNode.traverse(), unwrappedJavaType);
    }
}

和用法示例:

public class MyBean {

    @JsonProperty("broadcastPresenceRoles")
    @JsonUnwrapProperty
    private List<String> broadcastPresenceRole;

    @JsonProperty("admins")
    @JsonUnwrapProperty
    private String admin;

    // constructor, getter and setter
}

@JsonProperty用于定位包装器对象,@JsonUnwrappProperty用于反序列化json对象并将属性提取到带注释的字段中。

<强>编辑:

以下是ObjectMapper的示例:

String json = "{\n" +
        "  \"broadcastPresenceRoles\": {\n" +
        "    \"broadcastPresenceRole\": [\n" +
        "      \"moderator\",\n" +
        "      \"participant\",\n" +
        "      \"visitor\"\n" +
        "    ]\n" +
        "  },\n" +
        "  \"admins\": {\n" +
        "    \"admin\": \"sanjeet@shahanshah\"\n" +
        "  }\n" +
        "}";

final ObjectMapper mapper = new ObjectMapper();
final MyBean myBean = mapper.readValue(json, MyBean.class);

System.out.println(myBean.getBroadcastPresenceRole());
System.out.println(myBean.getAdmin());

输出:

  

[主持人,参与者,访客]

     

sanjeet @ shahanshah

答案 1 :(得分:0)

我根据@wilson 响应创建了一个解决 NPE 的变体

transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Resize((256, 256)),
    transforms.RandomHorizontalFlip(),
    transforms.FiveCrop((224, 224)),
    transforms.Lambda(lambda crops: torch.stack([transforms.Normalize(mean, std)(crop) for crop in crops]))    
])