Я пытаюсь сериализовать управляемый класс jpa (openjpa).
Этот класс содержит набор. Во время выполнения этот набор имеет тип org.apache.openjpa.util.java $ util $ LinkedHashSet $ proxy (мы используем openjpa).
Джексон сериализует этот штраф, но затем потерпит неудачу, когда дело доходит до десериализации, поскольку этот тип не может быть создан (и при использовании конфигурации jackson spring security он не попадает в белый список).
Итак, теперь я думаю, что решение состоит в том, чтобы настроить сериализацию, чтобы она была разделена и десериализована как более стандартный набор. Когда он десериализован, ему нужно только реализовать Set.
И я хочу попытаться избежать загрязнения постоянного класса (поэтому хочу использовать миксины).
Класс контейнера - это класс 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
И эта ошибка возникает при сериализации.
Так что похоже, что он не соблюдает установленный контейнер или что-то в этом роде.
Это правда - это допустимый класс и т. д. Но я подозреваю, что причина, по которой он не работает, в том, что Джексон не распознает это как коллекцию. Он поддерживает классы коллекций по умолчанию, а не пользовательские.




Итак, ответ, на который я остановился, основан на том, что Джексон не поддерживает нестандартные коллекции из коробки. Само собой разумеется, что из коробки будут работать только коллекции 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), пока это набор, которого нет ' t независимо от того, какая реализация. В этом случае я думаю, что это HashSet.
И я подозреваю, что это рекомендуемый / единственный способ успешно десериализовать коллекции, которые Джексон не поддерживает из коробки.
Почему его нельзя построить. Я только что успешно выполнил это: new org.apache.openjpa.util.java $ util $ LinkedHashSet $ proxy ();