【问题标题】:How can I deserialize a JSON array of "name" "value" pairs to a Pojo using Jackson如何使用 Jackson 将“名称”“值”对的 JSON 数组反序列化为 Pojo
【发布时间】:2014-01-22 15:58:02
【问题描述】:

我想反序列化以下 JSON 对象:

{
  "id":"001",
  "module_name":"Users",
  "name_value_list":
    {
      "user_name": {"name":"user_name", "value":"admin"},
      "full_name": {"name":"full_name", "value":"Lluís Pi"},
      "city": {"name":"full_name", "value":"Barcelona"},
      "postal_code": {"name":"postal_code", "value":"08017"},
      ...
    }
}

像这样进入一些 Java 对象:

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
public class UserEntry
{
  private String id;
  private String moduleName;
  private Person nameValueList;

  public String getId()
  {
    return id;
  }

  public String getModuleName()
  {
    return moduleName;
  }

  public Person getPerson()
  {
    return nameValueList;
  }
}

其中 Person 是以下类:

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
class Person 
{
  private String userName;
  private String fullName;
  private String city;
  private String postalCode;
}

使用 Jackson 但我收到反序列化错误。

如果我将字段 nameValueList 的类型更改为 Map,则所有反序列化过程都没有问题,我会得到一个映射,其中键是“名称”值,值是“值”值。

所以我的问题是:有没有简单的方法,或者没有那么简单的方法可以将这种 JSON 对象反序列化为具有 prop_1prop_2prop_3prop_4 属性的 Java Pojo?

{
  "name_value_list":
    {
      "prop_1": {"name":"prop_1", "value":"value_1"},
      "prop_2": {"name":"prop_2", "value":"value_2"},
      "prop_3": {"name":"prop_3", "value":"value_3"},
      "prop_4": {"name":"prop_4", "value":"value_4"},
      ...
    }
}

【问题讨论】:

    标签: java json jackson deserialization


    【解决方案1】:

    不是很简单,也不是很干净。但是,您可以通过为 Person 类中的 JSON 属性实现 any setter 字段来实现,这些属性与您的 UserEntry POJO 上的任何属性都不匹配。

    @JsonAnySetter
    public void putUserField(String userKey, Map<String, String> userValue) 
      throws NoSuchFieldException {
        String actualFieldName = getActualFieldName(userKey);
        Field field = this.getClass().getDeclaredField(actualFieldName);
        field.setAccessible(true);
        ReflectionUtils.setField(field, this, userValue.get("value"));
    }
    
    private String getActualFieldName(String userKey) {
        return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, userKey);
    }
    

    除此之外,我还必须将 Person 类的 Jackson 属性更改为

    @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.PUBLIC_ONLY, 
      getterVisibility = JsonAutoDetect.Visibility.NONE)
    

    它适用于“城市”等不需要任何名称转换的属性,因为杰克逊试图直接设置失败的字段。

    【讨论】:

    • 是的,我发现使用自省是一种解决方案,我的问题是这段代码必须在 java.beans.Introspector 不可用的 Android 上工作。您的 ReflectionUtils 课程来自哪里,您知道它是否适用于 Android。我一直在尝试使用 Jackson API 找到类似的方法,但文档不是很清楚。
    • ReflectionUtils 是 Spring 类,CaseFormat 是 Guava 类。我不确定 ReflectionUtils 是否适用于 Android。如果你有设置,你也可以在Android上测试上面的代码。
    • 好的。谢谢你。我找到了这个code.google.com/p/guava-libraries/wiki/Compatibility#Android
    • 是的,Spring ReflectionUtils 只使用 Android 可用的 Java 类。
    • 仅供参考:这是反射相关操作的另一个经典助手:commons.apache.org/proper/commons-beanutils
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-07
    • 2013-01-08
    • 1970-01-01
    • 1970-01-01
    • 2023-02-08
    • 2020-12-10
    相关资源
    最近更新 更多