杰克逊反序列化/序列化不对属性进行排序

时间:2017-07-05 14:08:33

标签: java sorting serialization jackson deserialization

我在我的应用程序中使用 Jackson 2.8.9 来生成一些JSON。我有一些单元测试,我将生成的JSON与一些文件内容进行比较。

当我将生成的JSON与我的文件内容进行比较时,由于属性顺序,它不匹配。

为了使测试可重复,我需要按字母顺序排序属性。但是对杰克逊来说,似乎没有用。

我为插图写了一些测试。只有should_indent_properties通过。

public class FormatJsonWithJacksonTest {

private static final String INDENTED_UNSORTED = "{\r\n" + 
        "  \"firstChild\" : {\r\n" + 
        "    \"subChild\" : {\r\n" + 
        "      \"alphaItem\" : \"1234567891234567\",\r\n" + 
        "      \"otherProperty\" : \"2017-06-21\",\r\n" + 
        "      \"someOtherProperty\" : \"NONE\",\r\n" + 
        "      \"alphaType\" : \"KIND_OF_TYPE\"\r\n" + 
        "    }\r\n" + 
        "  }\r\n" + 
        "}";

private static final String INDENTED_SORTED = "{\r\n" + 
        "  \"firstChild\" : {\r\n" + 
        "    \"subChild\" : {\r\n" + 
        "      \"alphaItem\" : \"1234567891234567\",\r\n" + 
        "      \"alphaType\" : \"KIND_OF_TYPE\",\r\n" + 
        "      \"otherProperty\" : \"2017-06-21\",\r\n" + 
        "      \"someOtherProperty\" : \"NONE\"\r\n" + 
        "    }\r\n" + 
        "  }\r\n" + 
        "}";

private static final String UNINDENTED_UNSORTED = "{" + 
        "\"firstChild\":{" + 
        "\"subChild\":{" + 
        "\"alphaItem\":\"1234567891234567\"," + 
        "\"otherProperty\":\"2017-06-21\"," + 
        "\"someOtherProperty\":\"NONE\"," + 
        "\"alphaType\":\"KIND_OF_TYPE\"" + 
        "}" + 
        "}" + 
        "}";

private static final String UNINDENTED_SORTED = "{" + 
        "\"firstChild\":{" + 
        "\"subChild\":{" + 
        "\"alphaItem\":\"1234567891234567\"," + 
        "\"alphaType\":\"KIND_OF_TYPE\"," + 
        "\"otherProperty\":\"2017-06-21\"," + 
        "\"someOtherProperty\":\"NONE\"" + 
        "}" + 
        "}" + 
        "}";

@Test
public void should_sort_properties() throws Exception {
    // Given
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper = objectMapper
            .configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true);

    // When
    String formattedJson = tryingToFormatJson(objectMapper, INDENTED_UNSORTED);

    // Then
    assertEquals(UNINDENTED_SORTED, formattedJson);
}


@Test
public void should_indent_properties() throws Exception {
    // Given
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper = objectMapper.enable(SerializationFeature.INDENT_OUTPUT);

    // When
    String formattedJson = tryingToFormatJson(objectMapper, UNINDENTED_UNSORTED);

    // Then
    assertEquals(INDENTED_UNSORTED, formattedJson);
}

@Test
public void should_sort_and_indent_properties() throws Exception {
    // Given
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper = objectMapper
            .configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true)
            .enable(SerializationFeature.INDENT_OUTPUT);

    // When
    String formattedJson = tryingToFormatJson(objectMapper, INDENTED_UNSORTED);

    // Then
    assertEquals(INDENTED_SORTED, formattedJson);
}

//
// Utils
//

private String tryingToFormatJson(ObjectMapper objectMapper, String unformattedJson)
        throws IOException, JsonProcessingException {
    JsonNode unsortedTree = objectMapper.readTree(unformattedJson);
    Object treeToValue = objectMapper.treeToValue(unsortedTree, Object.class);
    return objectMapper.writeValueAsString(treeToValue);
}

}
  • 我如何用杰克逊对JSON进行排序?
  • 您是否有任何解决方案来实施我的方法tryingToFormatJson
  • 杰克逊是我想做的合适工具吗?

1 个答案:

答案 0 :(得分:1)

当您致电objectMapper.treeToValue(unsortedTree, Object.class)时,Object的类型是Map的子类 - 只需要System.out.println(treeToValue.getClass())进行检查。

根据javadocSORT_PROPERTIES_ALPHABETICALLY不会对地图键进行排序:

  

定义用于POJO字段的默认属性序列化顺序的功能(注意:不适用于地图序列化!

如果要对字段进行排序,则必须为您的结构创建自定义类,如下所示:

public class Tree {
    private Map<String, Child> firstChild;

    // getters and setters
}

public class Child {
    private String alphaItem;

    private String otherProperty;

    private String someOtherProperty;

    private String alphaType;

    // getters and setters
}

并将treeToValue调用更改为:

Tree treeToValue = objectMapper.treeToValue(unsortedTree, Tree.class);

这样,字段将被排序,测试将起作用。