2014-05-18 4 views
2

Je souhaite écrire un désérialiseur personnalisé pour mon objet, mais pour ce faire, j'ai besoin d'accéder à une autre partie de l'objet désérialisé. Imaginez un objet JSON comme ceci:gson deserializing: Référence propriétaire de l'objet imbriqué

{ 
    "id": 2, 
    "name": "circle", 
    "dependencies": { 
     "donut": "e8ed7bbd8715de2f5a85930912fcf238" 
    }, 
    "someReference": { 
     "type": "Model", 
     "refersTo": "donut" 
    } 
} 

Je sais comment écrire un adaptateur/désérialiseur. Je sais aussi comment transformer le "e8ed7bbd8715de2f5a85930912fcf238" ​​en un objet Java via ancien. Qu'est-ce que je ne veux pas et que je voudrais savoir, c'est comment transformer mon "donut" en "e8ed7bbd8715de2f5a85930912fcf238" ​​ou l'objet Java ultime "pendant" la création. Cette information se situe dans le champ du parent, car "someReference" correspond à un autre objet Java. Ainsi, la classe de niveau supérieur est un Owner avec les champs:

public class Owner { 
    public int id; 

    public String name; 

    public List<String, Resource> dependencies; 

    public MyReference someReference; 
} 

id, name, dependencies tous les travaux jusqu'à présent. Donc: Comment puis-je référencer l'objet parent dans un processus de désérialisation? Est-ce seulement possible? Quelle serait une solution à ce que j'essaie de faire?

Répondre

1

J'ai écrit un désérialiseur qui fait ce que vous voulez (si j'ai bien compris). La seule différence par rapport à ce que vous avez demandé est que je ne sais pas ce que vous voulez dire par Reference, donc j'ai utilisé String à la place. Mais je pense que vous pouvez facilement adapter mon code.

Ma définition Propriétaire:

package stackoverflow.questions.q23718183; 

import java.util.*; 

public class Owner { 
    public int id; 

    public String name; 

    public Map<String, String> dependencies; 

    public MyReference someReference; 

    @Override 
    public String toString() { 
     return "Owner [id=" + id + ", name=" + name + ", dependencies=" + dependencies + ", someReference=" + someReference + "]"; 
    } 

    public static class MyReference { 
     String type; 
     String refersTo; 

     @Override 
     public String toString() { 
      return "MyReference [type=" + type + ", refersTo=" + refersTo + "]"; 
     } 

    } 

} 

Mon désérialiseur:

package stackoverflow.questions.q23718183; 

import java.io.IOException; 
import java.lang.reflect.Type; 
import java.util.*; 

import com.google.gson.*; 
import com.google.gson.stream.*; 
import com.google.gson.reflect.TypeToken; 

public class OwnerDeserializer implements JsonDeserializer<Owner> { 

    @Override 
    public Owner deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 
     if (json == null) 
      return null; 
     else { 
      Owner owner = new Owner(); 
      JsonObject jo = json.getAsJsonObject(); 

      owner.id = jo.get("id").getAsInt(); 
      owner.name = jo.get("name").getAsString(); 

      TypeToken<Map<String, String>> mapType = new TypeToken<Map<String, String>>() {}; 
      owner.dependencies = context.deserialize(jo.get("dependencies"), mapType.getType()); 

      Owner.MyReference reference = new Owner.MyReference(); 
      JsonObject jo2 = jo.get("someReference").getAsJsonObject(); 
      reference.type = jo2.get("type").getAsString(); 
      reference.refersTo = owner.dependencies.get(jo2.get("refersTo").getAsString()); 

      owner.someReference = reference; 

      return owner; 
     } 
    } 
} 

Mon code de test:

package stackoverflow.questions.q23718183; 

import com.google.gson.*; 

public class Q23718183 { 

    public static void main(String[] args) { 
     String s = " {               "+ 
       " \"id\": 2,             "+ 
       " \"name\": \"circle\",          "+ 
       " \"dependencies\": {          "+ 
       "  \"donut\": \"e8ed7bbd8715de2f5a85930912fcf238\"  "+ 
       " },               "+ 
       " \"someReference\": {          "+ 
       "  \"type\": \"Model\",         "+ 
       "  \"refersTo\": \"donut\"        "+ 
       " } "+ 
       "}"; 

     GsonBuilder b = new GsonBuilder(); 
     b.registerTypeAdapter(Owner.class, new OwnerDeserializer()); 
     Gson g = b.create(); 

     Owner o = g.fromJson(s, Owner.class); 

     System.out.println(o); 


    } 

} 

et voici le résultat:

Owner [id=2, name=circle, dependencies={donut=e8ed7bbd8715de2f5a85930912fcf238}, someReference=MyReference [type=Model, refersTo=e8ed7bbd8715de2f5a85930912fcf238]] 

Comme vous pouvez le voir, donut a été remplacé par sa valeur dans le nœud dependencies.

+1

Nice! C'est dommage car je ne voulais pas fouiller dans le OwnerDeserializer pour y arriver. J'aurais plutôt aimé un MyReferenceDeserializer qui obtient un propriétaire comme référence (ou simplement un JsonTree du "contexte" actuel dans lequel il se trouve). Quelque chose comme 'context.getParentNode(). Get (" dépendances "). Get (" donut ")' Je suppose que je n'ai pas d'autre choix alors. – Danyel