Сравнение JsonNode без полей - PullRequest
0 голосов
/ 03 ноября 2018

Я пытаюсь десериализовать строку JSON с помощью ObjectMapper (Джексон) и исключить поле при выполнении десериализации.

Мой код выглядит следующим образом:

String aContent = new String(Files.readAllBytes(Paths.get(aFile)));
String bContent = new String(Files.readAllBytes(Paths.get(bFile)));

ObjectMapper mapper = new ObjectMapper();

FilterProvider filterProvider = new SimpleFilterProvider()
      .addFilter("_idFilter", SimpleBeanPropertyFilter.serializeAllExcept("_id"));

mapper.setFilterProvider(filterProvider);

JsonNode tree1 = mapper.readTree(aContent);
JsonNode tree2 = mapper.readTree(bContent);

String x = mapper.writeValueAsString(tree1);

return tree1.equals(tree2);

И x, и tree1, и tree2 содержат значение _id в строке JSON, но оно не удалено.

Ответы [ 3 ]

0 голосов
/ 08 ноября 2018

Вы следуете Игнорировать поля, используя фильтры , кроме первого шага

Сначала нам нужно определить фильтр для объекта java:

@JsonFilter("myFilter")
public class MyDtoWithFilter { ... }

Так что в настоящее время вы должны добавить

@JsonFilter("_idFilter")
public class JsonNode {

Это невозможно, поэтому вам нужно создать класс, расширяющий JsonNode, и использовать его вместо

@JsonFilter("_idFilter")
public class MyJsonNode extends JsonNode {

Если вы не хотите реализовывать все абстрактные методы, определите как abstract

@JsonFilter("_idFilter")
public abstract class MyJsonNode extends JsonNode {
}

А в вашем коде:

MyJsonNode tree1 = mapper.readTree(aContent);
MyJsonNode tree2 = mapper.readTree(bContent);
0 голосов
/ 11 ноября 2018

Если вы используете Jackson 2.6 или выше, вы можете использовать FilteringParserDelegate с пользовательским TokenFilter.

public class PropertyBasedIgnoreFilter extends TokenFilter {

    protected Set<String> ignoreProperties;

    public PropertyBasedIgnoreFilter(String... properties) {
        ignoreProperties = new HashSet<>(Arrays.asList(properties));
    }

    @Override
    public TokenFilter includeProperty(String name) {
        if (ignoreProperties.contains(name)) {
            return null;
        }
        return INCLUDE_ALL;
    }
}

При создании FilteringParserDelegate с этим PropertyBasedIgnoreFilter убедитесь, что оба логических значения includePath и allowMultipleMatches равны true.

public class Main {
    public static void main(String[] args) throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        String jsonInput = "{\"_p1\":1,\"_p2\":2,\"_id\":\"id\",\"_p3\":{\"_p3.1\":3.1,\"_id\":\"id\"}}";

        JsonParser filteredParser = new FilteringParserDelegate(mapper.getFactory().createParser(new ByteArrayInputStream(jsonInput.getBytes())),
                                                                new PropertyBasedIgnoreFilter("_id"),
                                                                true,
                                                                true);
        JsonNode tree = mapper.readTree(filteredParser);

        System.out.println(jsonInput);
        System.out.println(tree);
        System.out.println(jsonInput.equals(tree.toString()));
    }
}

печать

{"_p1":1,"_p2":2,"_id":"id","_p3":{"_p3.1":3.1,"_id":"id"}}
{"_p1":1,"_p2":2,"_p3":{"_p3.1":3.1,"_id":"id"}}
false

Как видите, вложенные вхождения _id не отфильтровываются. В случае, если это не то, что вам нужно, вы, конечно, можете расширить мою PropertyBasedIgnoreFilter своей собственной реализацией TokenFilter.

0 голосов
/ 07 ноября 2018

FilterProvider предназначены для использования с пользовательским объектом, таким как здесь

Если вы хотите придерживаться JsonNode, используйте этот метод:

String aContent = new String("{\"a\":1,\"b\":2,\"_id\":\"id\"}"); 

ObjectMapper mapper = new ObjectMapper();

JsonNode tree1 = mapper.readTree(aContent);
ObjectNode object = (ObjectNode) tree1;
object.remove(Arrays.asList("_id"));

System.out.println(mapper.writeValueAsString(object));

Напечатает:

{"a":1,"b":2}
...