反序列化 JSON,其中键和值分别存储

问题描述

我有一个 JSON 结构,其中的键和值是这样存储的

[
  {
    "key": "firstName","value": "John"
  },{
    "key": "lastName","value": "Smith"
  }
]

我想反序列化数组,以便每个键都是一个属性名称,并分配适当的值。

public class Customer {

  private String firstName;
  private String lastName;

  public String getFirstName() {
    return this.firstName;
  }

  public void setFirstName(String firstName) {
    this.firstName = firstName;
  }

  public String getLastName() {
    return this.lastName;
  }

  public void setLastName(String lastName) {
    this.lastName = lastName;
  }
}

我曾想过创建一个自定义反序列化器来接受一组客户属性,并根据属性名称手动设置每个属性。我担心的是,随着添加更多属性,这种方法可能会变得脆弱,并且无法长期维护。

有谁知道我可能忽略的任何有助于反序列化的 Jackson 注释?

解决方法

只需用 @JsonProperty 注释属性

public class Customer {

@JsonProperty("key")
private String firstName;
@JsonProperty("value")
private String lastName;

.... 
}

如果你想在序列化过程中保留名称,你应该注释 setter 和 getter 而不是字段。

这是一个例子:Different names of JSON property during serialization and deserialization

,

这可以通过 Jackson 以一种非常通用的方式解决。

首先,您需要一个小的 Java 类来表示任何 键/值对(例如 {"key":"firstName","value":"John"}) 来自您的 JSON 输入。我们称之为Entry

public class Entry {

    private String key;
    private Object value;

    // getters and setters (omitted here for brevity)
}

使用上面的类可以反序列化 JSON 输入 (如您的问题中给出的)到一组 Entry 对象。

ObjectMpper objectMapper = new ObjectMapper();
File file = new File("example.json");
Entry[] entries = objectMapper.readValue(file,Entry[].class);

然后你可以把这个Entry[]数组转换成一个Map<String,Object>, 并进一步到 Customer 对象 (使用您的问题中给出的 Customer 类)。

Map<String,Object> map = Arrays.stream(entries)
        .collect(Collectors.toMap(Entry::getKey,Entry::getValue));
Customer customer = objectMapper.convertValue(map,Customer.class);
,

Jackson 将能够从 POJOJSON Object 反序列化 Map。您有一个 mini-Map 列表,其中每个 mini-Map 只包含一个属性。您需要:

  • 将输入负载反序列化为 List<Map<String,Object>>
  • 将其转换为单个 Map 对象
  • 转换为 Customer 实例

简单例子:

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class JsonMiniMapsApp {

    public static void main(String[] args) throws IOException {
        File jsonFile = new File("./resource/test.json").getAbsoluteFile();

        ObjectMapper mapper = new ObjectMapper();
        // read as list of maps
        List<Map<String,Object>> entries = mapper.readValue(jsonFile,new TypeReference<List<Map<String,Object>>>() {
        });

        // collect all values to single map
        Map<Object,Object> map = entries.stream().collect(Collectors.toMap(e -> e.get("key"),e -> e.get("value")));

        // convert to POJO
        Customer customer = mapper.convertValue(map,Customer.class);

        System.out.println(customer);
    }
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class Customer {

    private String firstName;
    private String lastName;
}

以上代码打印:

Customer(firstName=John,lastName=Smith)