シリアル化中に@JsonIgnoreのみを使用し、逆シリアル化は使用しない


325

サーバーとの間で送受信されるユーザーオブジェクトがあります。ユーザーオブジェクトを送信するときに、ハッシュされたパスワードをクライアントに送信したくありません。そこで、@JsonIgnorepasswordプロパティを追加しましたが、これにより、パスワードに逆シリアル化されないため、ユーザーがパスワードを取得していないときにユーザーをサインアップすることが難しくなります。

@JsonIgnore逆シリアル化ではなくシリアル化にのみ適用するにはどうすればよいですか?私はSpring JSONViewを使用しているので、をあまり制御できませんObjectMapper

私が試したこと:

  1. @JsonIgnoreプロパティに追加
  2. @JsonIgnoreゲッターメソッドのみを追加

回答:


481

これを正確に行う方法は、使用しているJacksonのバージョンによって異なります。これはバージョン1.9で変更されましたが、それより前は、@JsonIgnoreゲッターに追加することでこれを行うことができました。

あなたが試したもの:

ゲッターメソッドのみに@JsonIgnoreを追加する

これを行い@JsonProperty、JSON「パスワード」フィールド名の特定のアノテーションをオブジェクトのパスワードのセッターメソッドに追加します。

ジャクソンの最近のバージョンではREAD_ONLY、にWRITE_ONLYアノテーション引数が追加されていJsonPropertyます。したがって、次のようなこともできます:

@JsonProperty(access = Access.WRITE_ONLY)
private String password;

ドキュメントはここにあります


2
ジャクソンJSONのgist.github.com/thurloat/2510887は、デシリアライズのみで無視
Hadas

1
私の知る限り、まだセッターを実装して注釈を付ける必要があります。シリアライゼーション用のゲッターが欲しいだけです。あなたが話す一時的なものは何ですか?これはJPAアノテーションですAFAIK
Matt Broekhuis

3
また、フィールド自体から@JsonPropertyを必ず削除してください。そうしないと、ゲッター/セッターアノテーションが上書きされます
Anton Soradoi

15
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
Mikhail Batcer 2016年

1
Jackson-annotations 2.5には、後者の機能はありません。ジャクソンの注釈2.6.3ません
radiantRazor

98

これを実現するために必要なのは、2つの注釈だけです。

  1. @JsonIgnore
  2. @JsonProperty

使用する@JsonIgnoreクラスのメンバーとそのゲッターであり、@JsonPropertyそのセッターに。サンプルの図はこれを行うのに役立ちます:

class User {

    // More fields here
    @JsonIgnore
    private String password;

    @JsonIgnore
    public String getPassword() {
        return password;
    }

    @JsonProperty
    public void setPassword(final String password) {
        this.password = password;
    }
}

2
ジャクソン2.6.4でうまくいったのはそれだけです。@JsonProperty(access = Access.WRITE_ONLY)を使用するために最善を尽くしましたが、うまくいきませんでした。
cirovladimir 2017

77

バージョン2.6以降:より直感的な方法はcom.fasterxml.jackson.annotation.JsonProperty、フィールドで注釈を使用することです。

@JsonProperty(access = Access.WRITE_ONLY)
private String myField;

ゲッターが存在する場合でも、フィールド値はシリアル化から除外されます。

JavaDocは言う:

/**
 * Access setting that means that the property may only be written (set)
 * for deserialization,
 * but will not be read (get) on serialization, that is, the value of the property
 * is not included in serialization.
 */
WRITE_ONLY

逆に必要な場合は、を使用してくださいAccess.READ_ONLY


1
なぜ賛成票が少ないのかわかりません。これはこの問題を解決するエレガントな方法で、魅力のように機能します。ゲッター、セッター、フィールドに注釈を付ける必要はありません。フィールドのみ。ありがとう。
CROSP 2015

これはバージョン2.6以降で使用できます。fasterxml.github.io/ jackson
Daniel Beer

おそらく2.6以上のユーザーにとって最良の答えです。
David Dossot、2016

org.codehaus.jackson.annotateインポートを使用していないことを確認してください。@DanielBeerのソリューションは、Jackson 2.6.3で動作します。ジャクソンが更新された今、これは受け入れられる答えになるはずです。
ケントブル

13

私の場合、Spring MVCコントローラーから返されたオブジェクトを自動的に(逆)シリアル化するジャクソンがあります(Spring 4.1.6で@RestControllerを使用しています)。のcom.fasterxml.jackson.annotation.JsonIgnore代わりにを使用する必要がorg.codehaus.jackson.annotate.JsonIgnoreありました。それ以外の場合は、何もしませんでした。


1
これは非常に有用な回答であり、@ JsonIgnoreがジャクソンによって尊重されなかった理由のソースを見つけるのに本当に役立ちました...ありがとう!
クリントイーストウッド

2
"user": {
        "firstName": "Musa",
        "lastName": "Aliyev",
        "email": "klaudi2012@gmail.com",
        "passwordIn": "98989898", (or encoded version in front if we not using https)
        "country": "Azeribaijan",
        "phone": "+994707702747"
    }

@CrossOrigin(methods=RequestMethod.POST)
@RequestMapping("/public/register")
public @ResponseBody MsgKit registerNewUsert(@RequestBody User u){

        root.registerUser(u);

    return new MsgKit("registered");
}  

@Service
@Transactional
public class RootBsn {

    @Autowired UserRepository userRepo;

    public void registerUser(User u) throws Exception{

        u.setPassword(u.getPasswordIn());
        //Generate some salt and  setPassword (encoded -  salt+password)
        User u=userRepo.save(u);

        System.out.println("Registration information saved");
    }

}

    @Entity        
@JsonIgnoreProperties({"recordDate","modificationDate","status","createdBy","modifiedBy","salt","password"})
                    public class User implements Serializable {
                        private static final long serialVersionUID = 1L;

                        @Id
                        @GeneratedValue(strategy=GenerationType.AUTO)
                        private Long id;

                        private String country;

                        @Column(name="CREATED_BY")
                        private String createdBy;

                        private String email;

                        @Column(name="FIRST_NAME")
                        private String firstName;

                        @Column(name="LAST_LOGIN_DATE")
                        private Timestamp lastLoginDate;

                        @Column(name="LAST_NAME")
                        private String lastName;

                        @Column(name="MODIFICATION_DATE")
                        private Timestamp modificationDate;

                        @Column(name="MODIFIED_BY")
                        private String modifiedBy;

                        private String password;

                        @Transient
                        private String passwordIn;

                        private String phone;

                        @Column(name="RECORD_DATE")
                        private Timestamp recordDate;

                        private String salt;

                        private String status;

                        @Column(name="USER_STATUS")
                        private String userStatus;

                        public User() {
                        }
                // getters and setters
                }

4
コードがどのように機能するかを簡単に説明することも将来的には役立つかもしれません。
KWILLIAMS 2017

よし!ここで何をしようとしていますか?より多くの票を得ていますか?笑
バラジボガラムラマナラヤン

0

これを処理する別の簡単な方法allowSetters=trueは、注釈で引数を使用することです。これにより、パスワードをdtoに逆シリアル化できますが、containsオブジェクトを使用する応答本文にシリアル化しません。

例:

@JsonIgnoreProperties(allowSetters = true, value = {"bar"})
class Pojo{
    String foo;
    String bar;
}

両方foobarオブジェクトに移入されたが、唯一のfooが応答本体に書き込まれます。


それは私の間違いでした。あなたがすでにスニペットを修正していることに気づきませんでした。あなたの変更を見ると、Groovyでの私の長年の執筆が私を取り込んでいるようで、Javaへの私の翻訳は少々ラフでした。ごめんなさい!
Dhandley
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.