【问题标题】:Jackson deserialization/serialization does not sort properties杰克逊反序列化/序列化不排序属性
【发布时间】:2017-12-09 06:15:05
【问题描述】:

我在我的应用程序中使用 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);
}

}
  • 如何使用 Jackson 对 JSON 进行排序?
  • 你有什么解决方案可以实现我的方法tryingToFormatJson
  • Jackson 是我想要执行此操作的正确工具吗?

【问题讨论】:

  • 嗯,这就是我所说的糟糕测试。首先是这些硬编码的行尾,然后是您测试 Jackson 而不是您的代码的事实。你不需要测试杰克逊。
  • 感谢您的回答。我不想测试杰克逊,这里有一个硬编码的结尾来澄清我的需求。我想在我的测试中使用tryingToFormatJson 方法。

标签: java sorting serialization jackson deserialization


【解决方案1】:

当您调用 objectMapper.treeToValue(unsortedTree, Object.class) 时,Object 的类型是 Map 的子类 - 只需输入 System.out.println(treeToValue.getClass()) 即可检查。

根据javadocSORT_PROPERTIES_ALPHABETICALLY 不会对映射键进行排序:

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


如果你想对字段进行排序,你必须为你的结构创建一个自定义类,如下所示:

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);

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

【讨论】:

  • 非常感谢您的回答!它工作得很好。我还找到了另一种方式:使用org.skyscreamer.jsonassert.JSONAssert。我看起来像:JSONAssert.assertEquals(expectedJSON, actualJSON, JSONCompareMode.LENIENT) 而不是 assertEquals(expectedJSON, tryingToFormatJson(objectMapper, actualJSON));
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-24
  • 2015-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-27
相关资源
最近更新 更多