2016-11-21 7 views
0

In unserem Projekt analysieren wir JSON mit Jackson. Wir setzten das Feld saved nach Feld channelId. Problem ist, dass channelId Feld später als saved geparst wird. Also zu der Zeit, die wir Feld saved Feld channelId setzen wollen, ist Null. Wie können wir Feldabhängigkeit in JSON Deserialisierung gesetzt, so wird das Feld saved nach channelId eingestellt werden?Deserialize JSON mit Jackson mit Feldabhängigkeit

Dies ist Teil unserer JSON-Daten:

"message":{ 
      "data":{ 
       "text":"Some text" 
      }, 
      "saved_by":[ 
       2715, 
       1234 
      ], 
      "some_boolean_field":false, 
      "channel_id":8162 
      } 

Dies ist unser Entitätsklasse:

@JsonIgnoreProperties(ignoreUnknown = true) 
@org.parceler.Parcel(org.parceler.Parcel.Serialization.BEAN) 

public class Message { 

    @JsonProperty("channel_id") 
    protected long channelId; 

    protected boolean saved; 

    @JsonSetter("saved_by") 
    public void setSavedBy(Set<Long> savedBy) { 
     saved = savedBy.contains(getUserIdByChannelId(channelId)); 
    } 

    public long getChannelId() { 
     return channelId; 
    } 

    public void setChannelId(long channelId) { 
     this.channelId = channelId; 
    } 

    public boolean isSaved() { 
     return saved; 
    } 

    public void setSaved(boolean saved) { 
     this.saved = saved; 
    } 

    public void setData(JsonNode data) throws JsonProcessingException { 
     JsonNode textNode = data.get("text"); 
     text = textNode != null ? textNode.asText() : ""; 

     components = new ArrayList<>(); 
     JsonNode mediaNode = data.get("media"); 
     if (mediaNode != null) { 
      MessageComponent[] parsedComponents = AppSession.getInstance().getObjectMapper().treeToValue(mediaNode, MessageComponent[].class); 
      List<MessageComponent> components = Arrays.asList(parsedComponents).subList(0, parsedComponents.length < 4 ? parsedComponents.length : 4); 

      this.components.addAll(components); 
     } 

     mediaCount = components.size(); 
    } 

    } 

Voll JSON:

{ 
    "data":{ 
     "serial":66, 
     "updated_entity":"bookmark", 
     "bookmark":{ 
     "message":{ 
      "data":{ 
       "text":"hello" 
      }, 
      "counted_serial":748, 
      "saved_by":[ 
       26526, 
       27758 
      ], 
      "type":"UserMessage", 
      "is_reviewed":false, 
      "channel_id":8128, 
      "id":2841531, 
      "replied_message_data":null, 
      "is_blocked":false, 
      "is_deleted":false, 
      "updated_at":"2016-11-21T05:59:52.471Z", 
      "spam_reported_by":[ 

      ], 
      "created_at":"2016-11-19T15:40:17.027Z", 
      "uuid":"0b6ba58e-f5e1-4ee5-a9da-041dfc2c85cd", 
      "liked_by":[ 

      ], 
      "user":{ 
       "last_name":"M", 
       "id":4537, 
       "first_name":"John", 
       "is_deleted":false, 
       "avatar_thumb":"https:\/\/cdn.site.org\/uploads\/99ef4d68-6eaf-4ba6-aafa-74d1cf895d71\/thumb.jpg" 
      }, 
      "serial":934 
     }, 
     "id":6931, 
     "created_at":"2016-11-21T05:59:52.459Z", 
     "is_deleted":false, 
     "updated_at":"2016-11-21T05:59:52.459Z" 
     } 
    }, 
    "type":"action_performed" 
} 
+0

Wäre es möglich, diese eher von einem Konstruktor zu rekonstruieren als von Feldern einstellen? – chrylis

+0

Wenn das Feld 'gespeichert' ** immer ** abhängig von' channelId' ist, dann setze das Feld 'saved' in' setChannelId() '? –

+0

JSON Bestellung kann nicht garantiert werden. Zum Beispiel habe ich bei einigen Telefonen die richtige Reihenfolge erhalten, bei anderen ist die Reihenfolge anders. –

Antwort

1

Es ist ein bisschen hackish, sondern indem Die Message Klasse einen eigenen Deserialisierungs-Builder, Sie erhalten eine Art "Ready for Bean Creation" -Event, in dem Sie acc haben auf alle Eigenschaften.

Mein Vorschlag ist, dass Sie versuchen, die folgenden:

@JsonDeserialize(builder = Message.class) 
public class Message { 

    ... 

    @JsonSetter("saved_by") 
    public void setSavedBy(Set<Long> savedBy) { 
     // Merely store the value for later use. 
     this.savedBy = savedBy; 
    } 

    ... 

    public Message build() { 
     // Calculate value of "saved" field. 
     this.saved = this.savedBy.contains(getUserIdByChannelId(this.channelId)); 
     return this; 
    } 

    // Handling the added challenge. 
    @JsonProperty("data") 
    public void setData(JsonNode data) throws JsonProcessingException { 
     ... 
    } 
} 

Der obige Vorteil der Standardeinstellungen der JsonPOJOBuilder Anmerkung nimmt, nämlich, dass der Standardwert für buildMethodNamebuild ist.

+0

ich Ihren Code versucht, aber Objekt Einstellung nicht alle Felder aus. Muss ich alle Felder in 'build()' Methode setzen? –

+0

Nein, solange Setter vorhanden sind, sollten sie verwendet werden. Hast du versucht, ein paar Haltepunkte zu setzen, um zu sehen, ob sie getroffen werden? – Henrik

+0

Ich habe gerade meine Sandbox-Tests neu gestartet und sie funktionieren definitiv. Siehst du Fehler? Verwenden Sie die Deserialisierung wie folgt: 'Message message = om.readValue (json, Message.class);'? – Henrik

Verwandte Themen