Как сериализовать и десерализовать подкласс набора как известный набор с Джексоном 2 - PullRequest
0 голосов
/ 11 июня 2018

Я пытаюсь сериализовать управляемый класс jpa (openjpa).

Этот класс содержит набор.Во время выполнения этот набор имеет тип org.apache.openjpa.util.java $ util $ LinkedHashSet $ ​​proxy (мы используем openjpa).

Джексон выполнит сериализацию этого штрафа, но затем потерпит неудачу, когда придет десериализация какэтот тип не может быть создан (и при использовании конфигурации Джексона Spring Spring он не входит в белый список).

Так что теперь я думаю, что решение состоит в том, чтобы настроить сериализацию, чтобы она сортировалась и десериализовалась как более стандартный набор.Когда он десериализован, ему нужно только реализовать Set.

И я хочу попытаться избежать загрязнения постоянного класса (поэтому хочу использовать mixins).

Класс контейнера - это класс User, и онсодержит множество класса Role.Пока у меня есть:

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
public static class UserMixin {
    @JsonDeserialize(as = LinkedHashSet.class, contentAs = LinkedHashSet.class)
    @JsonSerialize(as = LinkedHashSet.class, contentAs = LinkedHashSet.class, typing = Typing.DYNAMIC)
    private Set<Role> roles;

}

Но когда я запускаю с этим, я получаю

Invalid definition for property roles (of type 'Lxxx/yyy/User;'): Can not refine serialization content type [simple type, class xxx.yyy.Role] into java.util.LinkedHashSet; types not related

И эта ошибка возникает при сериализации.

Таким образом, кажется, что он не соблюдает установленный контейнер или что-то.

1 Ответ

0 голосов
/ 12 июня 2018

Таким образом, ответ, который я решил, основан на том, что Джексон не поддерживает нестандартные коллекции из коробки.Само собой разумеется, что только наборы java sdk будут работать из коробки.

Так что я закончил тем же, что и Spring Security, с нестандартными коллекциями, которые он добавляет.

context.setMixInAnnotations(Collections.<Object>unmodifiableSet(Collections.emptySet()).getClass(), UnmodifiableSetMixin.class);

(из org.springframework.security.jackson2.CoreJackson2Module)

Итак, я сделал то же самое:

context.setMixInAnnotations(org.apache.openjpa.util.java$util$LinkedHashSet$proxy.class, OpenJpaLinkedHashSetProxyMixin.class);

Это означает, что я могу настроить, как Джексон обращается с этим классом.

Теперь Джексон сериализует эту коллекцию без проблем.Проблема когда-либо была с сериализацией.Джексон, кажется, поддерживает любой подкласс Set, когда дело доходит до сериализации.Он борется за десериализацию.

То, что делает Spring, - это предоставление собственного десериализатора для этого неизменяемого набора, и это, кажется, единственный способ пойти с этим.

Итак, миксин:

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
@JsonDeserialize(using = Deserializer.class)
public static class OpenJpaLinkedHashSetProxyMixin {

}

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

org.springframework.security.jackson2.UnmodifiableSetDeserializer

и это:

class UnmodifiableSetDeserializer extends JsonDeserializer<Set> {

    @Override
    public Set deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        ObjectMapper mapper = (ObjectMapper) jp.getCodec();
        JsonNode node = mapper.readTree(jp);
        Set<Object> resultSet = new HashSet<Object>();
        if (node != null) {
            if (node instanceof ArrayNode) {
                ArrayNode arrayNode = (ArrayNode) node;
                Iterator<JsonNode> nodeIterator = arrayNode.iterator();
                while (nodeIterator.hasNext()) {
                    JsonNode elementNode = nodeIterator.next();
                    resultSet.add(mapper.readValue(elementNode.traverse(mapper), Object.class));
                }
            } else {
                resultSet.add(mapper.readValue(node.traverse(mapper), Object.class));
            }
        }
        return Collections.unmodifiableSet(resultSet);
    }
}

Например, я просто возвращаю хэш-набор напрямую (без включения его в неизменяемый набор).

Я думаю, суть в том, что мне не нужно, чтобы сериализованный набор возвращался обратно втот же класс, из которого он получен (org.apache.openjpa.util.java $ util $ LinkedHashSet $ ​​proxy), поэтому, если это Set, не имеет значения, какая реализация.В этом случае я думаю, что реализация - это HashSet.

И я подозреваю, что это рекомендуемый / единственный способ успешно десериализовать коллекции, которые Джексон не поддерживает "из коробки".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...