8

次の JSON が使用され、「phones」または「emailAddresses」のいずれかが null の場合、NullPointerException が発生します。

JSON:

{
  "item": {
    "messages": {
      "user.phone.missing": {
        "type": "warning",
        "key": "user.phone.missing",
        "message": "User profile does not have a phone number",
        "code": null
      },
      "user.email.missing": {
        "type": "warning",
        "key": "user.email.missing",
        "message": "User profile does not have an email address",
        "code": null
      },
      "user.es.sync.failed": {
        "type": "error",
        "key": "user.es.sync.failed",
        "message": "Unable to sync user",
        "code": null
      }
    },
    "user": {
      "firstName": "Test",
      "middleInitial": null,
      "lastName": "User",
      "createdDt": "2016-04-20 19:50:03+0000",
      "updatedDt": null,
      "lastVerifiedDt": null,
      "status": "DEACTIVATED",
      "tokens": [
        {
          "tokenHash": "test hash",
          "tokenValue": "test dn",
          "createdDt": "2016-04-20 19:50:03+0000",
          "updatedDt": null,
          "status": "ENABLED"
        }
      ],
      "phones": null,
      "emailAddresses": null
    }
  },
  "status": "SUCCESS",
  "errors": []
}

そして、ここにスタックトレースがあります:

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: N/A (through reference chain: com.test.message.cte.CteItemResponse["item"]->com.test.message.cte.CteUserContext["user"]->com.test.User["phones"])
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty._throwAsIOE(SettableBeanProperty.java:510)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty._throwAsIOE(SettableBeanProperty.java:493)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.set(MethodProperty.java:116)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:98)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:295)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:464)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:98)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:295)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:464)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:98)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:295)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2888)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2041)
    at com.test.Test.main(Test.java:20)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
Caused by: java.lang.NullPointerException
    at com.test.User.setPhones(User.java:202)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.set(MethodProperty.java:114)
    ... 19 more

次のようにカスタム ObjectMapper を設定しています。

package com.test;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.util.ISO8601DateFormat;

public class MigrationObjectMapper extends ObjectMapper {
    private MigrationObjectMapper() {
        // do not serialize null value fields
        this.setSerializationInclusion(JsonInclude.Include.NON_NULL);

        configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    public static MigrationObjectMapper getMigrationObjectMapper(){
        return new MigrationObjectMapper();
    }
}

つまりCteUserContext cteUserContext = MigrationObjectMapper.getMigrationObjectMapper().convertValue(item.getItem(), new TypeReference<CteUserContext>(){});、エラーがスローされます。

CteUserContext の内部には、List と List を含む User オブジェクトがあります。これらは、オブジェクト マッパーの構成に基づいてシリアル化するべきではありませんか?

4

2 に答える 2

7

ロッキーのコメントごと:

setSerializationInclusion は、逆シリアル化ではなくシリアル化に対してのみ null 値を無視します。

User クラスで受信した「phones」の値が null の場合は処理していなかったため、NPE がスローされていました。null ではないことを確認するために更新しました。そうである場合、他のロジックの前に短絡します。

/**
 * @param phones The phones
 */
@JsonProperty("phones")
public void setPhones(List<Phone> phones) {
    if ((phones != null) && (phones.size() > 1)) {
        int primaryIndex = -1;
        Phone primaryPhone = null;

        for (Phone p : phones) {
            if (p.getIsPrimary()) {
                primaryIndex = phones.indexOf(p);
                primaryPhone = p;
                break;
            }
        }

        phones.remove(primaryIndex);
        phones.add(0, primaryPhone);
    }
    this.phones = phones;
} 
于 2016-04-21T12:52:44.697 に答える
1

プロパティが実際にJSONに存在するという事実は、マッパーがそれをNON_NULLとして扱っていないことを意味するかどうか疑問に思っていphonesます(つまり、欠落しておらず、存在しますが、null明示的に値を指定しています)

JsonInclude.Include.NON_DEFAULT代わりに使用してみてください。

それに失敗した場合、this.setSerializationInclusion() の代わりにクラスのアノテーションを使用してみましたか?

@JsonInclude(Include.NON_DEFAULT)
public class MigrationObjectMapper {
    ....
}
于 2016-04-20T22:50:52.157 に答える