2013-08-14 12 views
12

Używam Jackson do serializacji JSON (de) w połączeniu ze Spring. Mam jednak problem z polem w dwóch przypadkach.Duplikat pola JSON z Jacksonem

Mam abstrakcyjną klasę:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "mimeType") 
@JsonSubTypes({ 
    @JsonSubTypes.Type(value = ImageBookmarkJsonModel.class, name = "image/jpeg"), 
    @JsonSubTypes.Type(value = EpubBookmarkJsonModel.class, name = "application/epub+zip") 
}) 
public abstract class AbstractBookmarkJsonModel extends AbstractJsonModel { 
    protected String mimeType; 
    // Removed other fields for brevity 

    public String getMimeType() { 
     return mimeType; 
    } 

    public void setMimeType(String mimeType) { 
     this.mimeType = mimeType; 
    } 

    @Override 
    public String toString() { 
     ObjectMapper mapper = new ObjectMapper(); 

     try { 
      return mapper.writeValueAsString(this); 
     } catch (IOException e) { 
      throw new IllegalStateException("Cannot convert object of type " + this.getClass().toString() + " to JSON", e); 
     } 
    } 
} 

a konkretną klasę przedłużyć streszczenie:

public class EpubBookmarkJsonModel extends AbstractBookmarkJsonModel { 
    private static final long serialVersionUID = 1L; 
    // Removed other fields for brevity 

    public EpubBookmarkJsonModel() { 
     this.mimeType = "application/epub+zip"; 
    } 
} 

Problem polega na tym, że kiedy serializacji ten JSON, otrzymuję duplikaty mimeType pole:

{ 
    "mimeType": "application/epub+zip", 
    "mimeType": "application/epub+zip", 
    "userId": 24, 
    "acid": "ACID-000000000029087", 
    "added": "2013-08-14T12:02:17Z", 
    "epubBookmarkId": 34, 
    "cfi": "epubcfi(/6/4!/2/68)", 
    "context": "CONTEXT" 
} 

Próbowałem użyć zalecenia previousanswers, aby użyć adnotacji @JsonAutoDetect w celu określenia, że ​​powinny być używane tylko pola w klasie, a także ustawienie jej na ObjectMapper, ale to nie rozwiązuje problemu.

Adnotacja:

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, 
     setterVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.NONE, 
     isGetterVisibility = JsonAutoDetect.Visibility.NONE) 

ObjectMapper:

ObjectMapper mapper = new ObjectMapper(); 
    mapper.getSerializationConfig().getDefaultVisibilityChecker() 
      .withFieldVisibility(JsonAutoDetect.Visibility.ANY) 
      .withGetterVisibility(JsonAutoDetect.Visibility.NONE) 
      .withSetterVisibility(JsonAutoDetect.Visibility.NONE) 
      .withCreatorVisibility(JsonAutoDetect.Visibility.NONE); 
+0

Nie wiem, czy jest to pomocne lub nie, ale jeśli usunąć adnotację '@JsonTypeInfo (korzystanie = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "mimeType") 'from' AbstractBookmarkJsonModel' to będziesz miał tylko jeden 'mimeType' w twoim jsonie – Katona

Odpowiedz

5

Takie zachowanie jest spowodowane przez adnotacje umieszczone na klasy AbstractBookmarkJsonModel:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "mimeType") 
@JsonSubTypes({ 
    @JsonSubTypes.Type(value = ImageBookmarkJsonModel.class, name = "image/jpeg"), 
    @JsonSubTypes.Type(value = EpubBookmarkJsonModel.class, name = "application/epub+zip") 
}) 

@JsonTypeInfo mówi Jackson do serializacji logiczną nazwę typu (JsonTypeInfo.Id.NAME) jako profesjonalista perty (JsonTypeInfo.As.PROPERTY) o nazwie mimeType (property = "mimeType"). Z @JsonSubTypes.Type przypisujesz nazwę logiczną application/epub+zip do EpubBookmarkJsonModel.

Jeśli chodzi o serializacji, Jackson serializuje nazwę logiczną jako własność mimeType = "application/epub+zip" następnie właściwości obiektu wśród nich mimeType co zdarza się mieć taką samą wartość jak logicznej nazwy application/epub+zip (przypisanym w konstruktora).

myślę mimeType należy zmienić objectType w @JsonTypeInfo adnotacji lub nawet lepiej, aby usunąć pole mimeType od Jackson zajmie typ informacji, które poprzez serializacji.

+1

+1 to jest właściwa odpowiedź, Jackson dodaje dodatkową właściwość do zserializowanego wyjścia JSON do zidentyfikować podtyp. W twoim przypadku próbujesz użyć istniejącej nieruchomości, nie powinieneś tego robić. Wiem, że nie można usunąć właściwości 'mimeType' z klasy, ponieważ myślę, że jej potrzebujesz. Po prostu użyj innej nazwy właściwości informacji podtypu, np. 'SubtypeName', a jako nazwy podtypów użyj czegoś w stylu" 'ImageBookmark'" i "' EpubBookmark' ". Jest to zamierzone użycie systemu Jacksons Polymorphic Type Handling. –

6

Wystąpił ten sam problem z duplikatem wyjścia. Znalazłem rozwiązanie, które nie obejmowało innej własności i pozwoliło mi nie usunąć pierwotnej własności. Najpierw ustawiam flagę visible na true dla JsonTypeInfo. Następnie dodałem adnotację JsonIgnore do deklaracji właściwości i pobierającego (ale nie do ustawiacza). Do tej pory wyprowadzanie JSON poprawnie tylko z jednym kluczem dla właściwości type.

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, visible = true, property = "mimeType") 
@JsonSubTypes({ 
    @JsonSubTypes.Type(value = ImageBookmarkJsonModel.class, name = "image/jpeg"), 
    @JsonSubTypes.Type(value = EpubBookmarkJsonModel.class, name = "application/epub+zip") 
}) 
public abstract class AbstractBookmarkJsonModel extends AbstractJsonModel { 
    @JsonIgnore 
    @JsonProperty("mimeType") 
    protected String mimeType; 

    @JsonIgnore 
    @JsonProperty("mimeType") 
    public String getMimeType() { 
     return mimeType; 
    } 

    @JsonProperty("mimeType") 
    public void setMimeType(String mimeType) { 
     this.mimeType = mimeType; 
    } 

} 

Warto zaznaczyć, że jest to z fasterxml Jackson-DataBind 2.1.1

<dependency> 
    <groupId>com.fasterxml.jackson.core</groupId> 
    <artifactId>jackson-databind</artifactId> 
    <version>2.1.1</version> 
</dependency> 
15

I rozwiązać to za pomocą JsonTypeInfo.As.EXISTING_PROPERTY z adnotacją @JsonTypeInfo.

Projekt jest open source, to sprawdzić tutaj: ANS.java

+1

Dobre rozwiązanie, z visible = true na @JsonTypeInfo (jeśli nie, właściwość ma wartość zerową po serializacji) –

+0

To powinna być akceptowana odpowiedź, moim zdaniem. To najczystsze użycie Jacksona. –

+0

To działało na "toJson()", ale kiedy próbowałem "fromJson()" pole pozostało z wartością "null". jakieś pomysły? – ozma

Powiązane problemy