2017-03-27 12 views
2

JSON API用のSDKを作成していますが、私は一見奇妙な問題に遭遇しています。 APIはPOSTデータの検証が非常に厳密で、idのようにリソースを更新する際に特定のパラメータが存在することを許可していません。このため、私は@Expose(serialize = false)私のリソースクラスのIDフィールドを追加しました。しかし、依然としてこのフィールドをシリアライズし、要求が拒否されるようです。次のようにリソースクラスは、おおよそ次のとおりです。Gson:@Expose(serialize = false)を持っていてもパラメータがシリアル化される

public class Organisation extends BaseObject 
{ 
    public static final Gson PRETTY_PRINT_JSON = new GsonBuilder() 
      .setPrettyPrinting() 
      .create(); 

    @Expose(serialize = false) 
    @SerializedName("_id") 
    private String id; 

    @SerializedName("email") 
    private String email; 

    @SerializedName("name") 
    private String name; 

    @SerializedName("parent_id") 
    private String parentId; 

    public String toJson() 
    { 
     return PRETTY_PRINT_JSON.toJson(this); 
    } 
} 

私のユニットテストは、クラス・パラメータとしてテストクラスに新しく作成されたインスタンスを保存し、APIを介してOrganisationのインスタンスを作成して、アップデートをテストしますupdateメソッドを呼び出します新しいリソースを更新してSDKを実装するこれが間違っているところです。 toJson()メソッドが新しいOrganisationで呼び出されて、更新要求のためにJSONにシリアル化される場合、_idフィールドは引き続き存在し、APIが更新を拒否します。テストコードは以下の通りです。コード内のコメントに注目してください。

@Test 
public void testCreateUpdateAndDeleteOrganisation() throws RequestException 
{ 
    Organisation organisation = new Organisation(); 
    organisation.setParentId(this.ORGANISATION_ID); 
    organisation.setName("Java Test Organisation"); 

    Organisation newOrganisation = this.MySDK.organisation.create(organisation); 
    this.testOrganisation(newOrganisation); 
    this.newOrganisation = newOrganisation; 

    this.testUpdateOrganisation(); 
} 

public void testUpdateOrganisation() throws RequestException 
{ 
    // I tried setting ID to null, but that doesn't work either 
    // even though I've set Gson to not serialise null values 
    this.newOrganisation.setId(null); 
    this.newOrganisation.setName(this.newName); 

    // For debugging 
    System.out.println(this.newOrganisation.toJson()); 

    Organisation updatedOrganisation = this.MySDK.organisation.update(this.newOrganisation.getId(), this.newOrganisation); 

    this.testOrganisation(updatedOrganisation); 
    assertEquals(newOrganisation.getName(), this.newName); 

    this.testDeleteOrganisation(); 
} 

誰でも私が間違っていることを発見できますか?私はインスタンスに既にIDの価値があるという事実と関係があると感じていますが、明示的にそれを連載しないように伝えるのは問題ではありませんか?

ご協力いただきありがとうございます。

EDIT:this.MySDK.organisation.update(this.newOrganisation.getId(), this.newOrganisation);には、組織インスタンスは編集されません。指定されたIDは、SDKがPOSTするURLに単に追加されます(POST /organisation/{id}

+0

代わりに 'transient'を試してみてください。 –

+0

@ cricket_007これまでにしたことがありますが、逆シリアル化では無視されます。私は '@ Expose'を使ってそれ以上の制御をしました –

+1

これを見ましたか? https://futurestud.io/tutorials/gson-model-annotations-how-to-ignore-fields-with-expose –

答えて

2

GsonBuilder().excludeFieldsWithoutExposeAnnotation()が追加されていない限り、@Exposeは無視される@peitekに感謝します。しかし、私は、シリアル化で1つのフィールドを無視するために、私のモデルクラスのすべての単一のパラメータに@Exposeを追加する必要があるので、このルートを使用しないことを選択します。代わりに、私はExclusionStrategyを書いて、パラメータ上にカスタムSkipSerialisation注釈の存在をチェックしました。

public static final Gson PRETTY_PRINT_JSON = new GsonBuilder() 
     .addSerializationExclusionStrategy(new ExclusionStrategy() 
     { 
      @Override 
      public boolean shouldSkipField(FieldAttributes f) 
      { 
       return f.getAnnotation(SkipSerialisation.class) != null; 
      } 

      @Override 
      public boolean shouldSkipClass(Class<?> clazz) 
      { 
       return false; 
      } 
     }) 
     .setPrettyPrinting() 
     .create(); 

および注釈:戦略と完全GsonBuilder

:私は次のようにこれらを実装

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.FIELD) 
public @interface SkipSerialisation 
{ 
} 

今、私はちょうど

@SkipSerialisation 
@SerializedName("_id") 
private String id; 

を行うことができ、それが動作します!

+0

'f.getAnnotation(SkipSerialisation.class)!= null'は' f.isAnnotationPresent(SkipSerialisation.class) 'に置き換えることができます。 –

+0

@LyubomyrShaydarivさらに良い!私はそれを使用します –

+0

@LyubomyrShaydariv Gsonのバージョンはそれですか?私はその方法がありません。 –

4

コメントに記載されているように、はtransientよりも良い選択です。 デフォルトのGsonインスタンスは、@Expose注釈を考慮していないことに注意してください。オプションとして設定しても無視されます。

@Exposeオプションを有効にする場合は、Gsonをカスタマイズする必要があります。上記のコードに基づいて、それを変更します。

public static final Gson PRETTY_PRINT_JSON = new GsonBuilder() 
     .setPrettyPrinting() 
     .excludeFieldsWithoutExposeAnnotation(); 
     .create(); 

あなた@Expose(serialize = false)アクティブと直列化の際に除外すべきです。

+0

こんにちは、あなたの答えに感謝します。私は 'excludeFieldsWithoutExposeAnnotation()'が名前が示唆したとおりに行ったと思っていましたが、何か具体的なことをしたいのであれば、 'Expose'は動作します。つまり、すべてのモデルのすべてのフィールドにExposeを追加する必要がありますか? –

+0

はい、同意します。その関数名は理想的ではありません。もちろん、関連するモデルのすべてのフィールドに少なくとも@Expose()を追加する必要があります。 – peitek

関連する問題