2013-08-13 8 views
6

ho il seguente metodo che uso per ottenere l'oggetto convertito in yaml rappresentazione (che posso ad esempio la stampa di consolarla.)Java SnakeYaml - impedire il dumping nomi di riferimento

@Nonnull 
private String outputObject(@Nonnull final ObjectToPrint packageSchedule) { 
    DumperOptions options = new DumperOptions(); 
    options.setAllowReadOnlyProperties(true); 
    options.setPrettyFlow(true); 
    return new Yaml(new Constructor(), new JodaTimeRepresenter(), options).dump(ObjectToPrint); 
} 

Tutto è buono, ma per qualche oggetto contenuto nella struttura ObjectToPrint Ricevo qualcosa come il nome di riferimento e non il contenuto dell'oggetto reale, ad es.

!!com.blah.blah.ObjectToPrint 
businessYears: 
- businessYearMonths: 12 
    ppiYear: &id001 { 
    endDate: 30-06-2013, 
    endYear: 2013, 
    startDate: 01-07-2012, 
    startYear: 2012 
    } 
    ppiPeriod: 
    ppiYear: *id001 
    endDate: 27-03-2014 
    startDate: 21-06-2013 
    units: 24.000 
    number: 1 

Come si può vedere dall'esempio precedente ho ppiYear oggetto stampato (contrassegnato come $id001) e lo stesso oggetto viene utilizzato in ppiPeriod ma solo il nome di riferimento viene stampato lì, non il contenuto dell'oggetto. Come stampare il contenuto dell'oggetto ogni volta che utilizzo quell'oggetto all'interno della mia struttura, che voglio convertire in yaml (ObjectToPrint). PS. Sarebbe bello non stampare il nome di riferimento (&id001) ma questo non è fondamentale

risposta

4

Questo perché si fa riferimento allo stesso oggetto in luoghi diversi. Per evitare ciò è necessario creare copie di tali oggetti. Yaml non ha un flag per disattivarlo, perché potresti entrare in loop senza fine in caso di riferimenti ciclici. Tuttavia si potrebbe modificare Yaml codice sorgente di ignorare doppi riferimenti:

sguardo Serializer linea ~ metodo 170 serializeNode:

... 
if (this.serializedNodes.contains(node)) { 
    this.emmitter.emit(new AliasEvent(...)); 
} else { 
    serializedNodes.add(node); // <== Replace with myHook(serializedNodes,node); 
... 

void myHook(serializedNodes,node) { 
    if (node's class != myClass(es) to avoid) { 
     serializedNodes.add(node); 
    } 

se si trova un modo per evitare Yaml di mettere i nodi nella collezione serializedNodes, la vostra il problema verrà risolto, tuttavia il tuo programma si interromperà in caso di riferimenti ciclici.

La soluzione migliore consiste nell'aggiungere un hook che evita di registrare solo la classe che si desidera venga scritta in modo chiaro.

+0

Ho appena commentato ** if (this.serializedNodes.contains (node)) { this.emitter.emit (new AliasEvent (tAlias, null, null)); } else {** dal metodo serializeNode e ** anchorNode (nodo); ** dal metodo serialize. Questo ha impedito di creare ancore e alias. – Ajeesh

+0

Questo è ciò che l'OP chiedeva :-). È necessario implementare myHook correttamente per disattivare solo il rilevamento ref per alcune classi. –