Принудительно использовать тег YAML для свойств JavaBean

Я использую SnakeYAML для определенной сериализации / десериализации. В моем приложении сочетаются Python и Java, поэтому мне нужно «разумное поведение» для тегов и типов.

Моя проблема / фактический статус в документе YAML:

!!mypackage.MyClassA
someFirstField: normal string
someSecondField:
  a: !!mypackage.ThisIsIt
    subField: 1
    subOtherField: 2
  b: !!mypackage.ThisIsIt
    subField: 3
    subOtherField: 4
someThirdField:
  subField: 5
  subOtherField: 6

Я добился использования тегов внутри коллекций (см. Пример someSecondField), повторно реализовав checkGlobalTag и просто выполнив return. Это, если я правильно понял, не обеспечивает интеллектуальной чистоты snakeyaml и поддерживает теги. Пока все хорошо: мне нужен шрифт везде.

Однако этого недостаточно, потому что someThirdField также является !!mypackage.ThisIsIt, но имеет неявный тег, и это проблема (Python этого не понимает). Есть и другие угловые случаи, которые не относятся к делу (пытался воспользоваться некоторыми ярлыками на стороне Python, и они стали плохой идеей).

Как правильно обеспечить отображение тегов для всех пользовательских классов? Я предполагаю, что мне следует переопределить некоторые методы в Representer, но я не смог найти, какой из них.


person MariusSiuram    schedule 13.06.2016    source источник


Ответы (1)


Строка, отвечающая за эту "автоматическую очистку смарт-тегов", следующая:

if (property.getType() == propertyValue.getClass())

Который можно найти в representJavaBeanProperty, для класса Representer.

(Уродливое) решение, которое я нашел, - это расширить Representer и @Override на representJavaBeanProperty следующим:

protected NodeTuple representJavaBeanProperty(Object javaBean, 
        Property property,
        Object propertyValue, 
        Tag customTag) {
    // Copy paste starts here...

    ScalarNode nodeKey = (ScalarNode) representData(property.getName());
    // the first occurrence of the node must keep the tag
    boolean hasAlias = this.representedObjects.containsKey(propertyValue);

    Node nodeValue = representData(propertyValue);

    if (propertyValue != null && !hasAlias) {
        NodeId nodeId = nodeValue.getNodeId();
        if (customTag == null) {
            if (nodeId == NodeId.scalar) {
                if (propertyValue instanceof Enum<?>) {
                    nodeValue.setTag(Tag.STR);
                }
            }
            // Copy-paste ends here !!!
            // Ignore the else block --always maintain the tag.
        }
    }

    return new NodeTuple(nodeKey, nodeValue);

Это также вызывает поведение явных тегов в списках (ранее выполнялось путем переопределения метода checkGlobalTag, теперь уже реализовано в коде representJavaBeanProperty).

person MariusSiuram    schedule 14.06.2016