Xstream

7 respostas
H

Preciso que o XStream imprima uma tag vazia quando o atributo da classe for nulo.

Exemplo:

public class Pessoa {
        String nome = "João";
        String sobrenome = null;
}

Resulte no xml :

João

Já tentei implementar um converter para fazer isso, mas quando o atributo é nulo o converter não é invocado.

Alguém pode me dar uma luz do que fazer?

Obrigado

7 Respostas

alves.Felipe

uma alternativa
http://www.guj.com.br/posts/list/57046.java

viniciusfaleiro

http://xstream.codehaus.org/annotations-tutorial.html

H

Pessoal,

Obrigado pela atençao, mas as sugestões não se enquadram no meu problema.

No link que o alves.Felipe me passou ele dá a sugestão de passar a string vazia ("") como sendo o alor nulo.
Isto pra mim não resolve todos os problemas, pois tenho campos de data e números que também pode ter valores nulo.
Outro problema é que a string vazia gera e não .

No link que o viniciusfaleiro enviou sobre annotation, eu já tinha visto antes, mas não encontrei nenhuma que me garantisse que a tag seria impressa, mesmo sendo nula.

Se mais alguém tiver alguma idéia, fico grato.

altitdb

hlima,

você conseguiu resolver seu problema?

Estou com um problema semelhante ao seu!

Obrigado.

H

Consegui resolver apenas sobrescrevendo uma classe da biblioteca.

A alteração que fiz foi no método doMarshal da classe com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter deixando-o da seguinte forma:

protected void doMarshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
        final Set seenFields = new HashSet();
        final Map defaultFieldDefinition = new HashMap();

        // Attributes might be preferred to child elements ...
         reflectionProvider.visitSerializableFields(source, new ReflectionProvider.Visitor() {
            public void visit(String fieldName, Class type, Class definedIn, Object value) {
                if (!mapper.shouldSerializeMember(definedIn, fieldName)) {
                    return;
                }
                if (!defaultFieldDefinition.containsKey(fieldName)) {
                    Class lookupType = source.getClass();
                    // See XSTR-457 and OmitFieldsTest
                    // if (definedIn != source.getClass() && !mapper.shouldSerializeMember(lookupType, fieldName)) {
                    //    lookupType = definedIn;
                    // }
                    defaultFieldDefinition.put(fieldName, reflectionProvider.getField(lookupType, fieldName));
                }
                
                SingleValueConverter converter = mapper.getConverterFromItemType(fieldName, type, definedIn);
                if (converter != null) {
                    if (value != null) {
                        if (seenFields.contains(fieldName)) {
                            throw new ConversionException("Cannot write field with name '" + fieldName 
                                + "' twice as attribute for object of type " + source.getClass().getName());
                        }
                        final String str = converter.toString(value);
                        if (str != null) {
                            writer.addAttribute(mapper.aliasForAttribute(mapper.serializedMember(definedIn, fieldName)), str);
                        }
                    }
                    // TODO: name is not enough, need also "definedIn"! 
                    seenFields.add(fieldName);
                }
            }
        });

        // Child elements not covered already processed as attributes ...
        reflectionProvider.visitSerializableFields(source, new ReflectionProvider.Visitor() {
            public void visit(String fieldName, Class fieldType, Class definedIn, Object newObj) {
                if (!mapper.shouldSerializeMember(definedIn, fieldName)) {
                    return;
                }
                
                System.out.println(fieldName + "=" + newObj);
                //if (!seenFields.contains(fieldName) && newObj != null) {
                if (!seenFields.contains(fieldName)) {
                    Mapper.ImplicitCollectionMapping mapping = mapper.getImplicitCollectionDefForFieldName(source.getClass(), fieldName);
                    if (mapping != null) {
                        if (mapping.getItemFieldName() != null) {
                            Collection list = (Collection) newObj;
                            for (Iterator iter = list.iterator(); iter.hasNext();) {
                                Object obj = iter.next();
                                writeField(fieldName, obj == null ? mapper.serializedClass(null) : mapping.getItemFieldName(), mapping.getItemType(), definedIn, obj);
                            }
                        } else {
                            context.convertAnother(newObj);
                        }
                    } else {

                        writeField(fieldName, null, fieldType, definedIn, newObj);
                    }
                }
            }

            private void writeField(String fieldName, String aliasName, Class fieldType, Class definedIn, Object newObj) {
                ExtendedHierarchicalStreamWriterHelper.startNode(writer, aliasName != null ? aliasName : mapper.serializedMember(source.getClass(), fieldName), fieldType); 

                if (newObj != null) {
                    Class actualType = newObj.getClass();
                    Class defaultType = mapper.defaultImplementationOf(fieldType);
                    if (!actualType.equals(defaultType)) {
                        String serializedClassName = mapper.serializedClass(actualType);
                        if (!serializedClassName.equals(mapper.serializedClass(defaultType))) {
                            String attributeName = mapper.aliasForSystemAttribute("class");
                            if (attributeName != null) {
                                writer.addAttribute(attributeName, serializedClassName);
                            }
                        }
                    }
    
                    final Field defaultField = (Field)defaultFieldDefinition.get(fieldName);
                    if (defaultField.getDeclaringClass() != definedIn) {
                        String attributeName = mapper.aliasForSystemAttribute("defined-in");
                        if (attributeName != null) {
                            writer.addAttribute(attributeName, mapper.serializedClass(definedIn));
                        }
                    }
    
                    Field field = reflectionProvider.getField(definedIn,fieldName);
                    marshallField(context, newObj, field);
                }
                writer.endNode();
            }

        });
    }

Anexei a classe nesta mensagem.

altitdb

Valeu cara…

Vou ver oq faço por aqui!!

xD~~

B

Depois de apanhar um pouco com a ultima versão, fiz a modificação e segue ai.

Criado 13 de dezembro de 2010
Ultima resposta 27 de mar. de 2012
Respostas 7
Participantes 5