在Jackson中自动String to int []转换

时间:2018-03-19 10:28:00

标签: java arrays json jackson

我有一个简单的POJO:

public class Entry {
    private Integer day;
    private String site;
    private int[] cpms;
    ... // getters/setters/constructor
}

我想阅读的日志文件似乎是:

{ "day":"1", "site":"google.com", "cpms":"[1,2,3,4,5,6,7]"}

Jackson根据文档自动将String转换为Integer。但它不适用于现场" cpms"。阅读它的最佳方法是什么? 我知道我可以定义" cpms"在构造函数中作为字符串,然后解析此字符串从中执行数组,如下所示:

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true);
this.cpm = objectMapper.readValue(cpms, int[].class);

但是有没有智能转换?

2 个答案:

答案 0 :(得分:2)

此转换也可以使用自定义JsonDeserializer完成。

1)实现专用的反序列化器类,例如:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;

import java.io.IOException;

public class IntArrayDeserializer extends StdDeserializer<int[]> {

  public IntArrayDeserializer() {
    super(int[].class);
  }

  @Override
  public int[] deserialize(JsonParser jsonParser,
                           DeserializationContext deserializationContext) throws IOException {
    String arrayAsString = jsonParser.getText();
    if (arrayAsString.length() == 2) { // case of empty array "[]"
      return new int[0];
    }
    String[] strIds = arrayAsString.substring(1, arrayAsString.length() - 1).split(",");
    return Arrays.stream(strIds).mapToInt(Integer::parseInt).toArray();
  }

}

2)在@JsonDeserialize(using = IntArrayDeserializer.class)字段上添加Entry.cpms

3)现在下面的测试应该通过:

@Test
public void deserializeExample() throws IOException {
  String json = "{ \"day\":\"1\", \"site\":\"google.com\", \"cpms\":\"[1,2,3,4,5,6,7]\"}";
  ObjectMapper mapper = new ObjectMapper();
  Entry entry = mapper.readValue(json, Entry.class);
  int[] expected = new int[] { 1, 2, 3, 4, 5, 6, 7 };
  assertTrue(Arrays.equals(expected, entry.getCpms()));
} 

这种方法的优点是,如果有其他字段以相同的方式转换,这个解串器是可重用的,它与Jackson API一致,并且不需要实现临时解决方案。

答案 1 :(得分:2)

据我所知,杰克逊没有任何内置的解决方案。你的数组用引号括起来,所以它是一个字符串。但是,有些方法可能适合您:

JSON创建者

定义用@JsonCreator注释的构造函数,然后解析字符串:

public class Entry {

    private Integer day;
    private String site;
    private int[] cpms;

    @JsonCreator
    public Entry(@JsonProperty("cpms") String cpms) {
        String[] values = cpms.replace("[", "").replace("]", "").split(",");
        this.cpms = Arrays.stream(values).mapToInt(Integer::parseInt).toArray();
    }

    // Getters and setters
}

自定义反序列化程序

编写自己的反序列化程序,然后可以在其他bean中重用它:

public class QuotedArrayDeserializer extends JsonDeserializer<int[]> {

    @Override
    public int[] deserialize(JsonParser jp, 
                             DeserializationContext ctxt) throws IOException {
        String rawValue = jp.getValueAsString();
        String[] values = rawValue.replace("[", "").replace("]", "").split(",");
        return Arrays.stream(values).mapToInt(Integer::parseInt).toArray();
    }
}
public class Entry {

    private Integer day;
    private String site;

    @JsonDeserialize(using = QuotedArrayDeserializer.class)
    private int[] cpms;

    // Getters and setters
}