web-dev-qa-db-ja.com

文字列値( '')から逆シリアル化する文字列引数コンストラクター/ファクトリーメソッドはありません

com.fasterxml.jackson.databindパッケージのObjectMapperクラスを使用すると、json解析の問題が発生します。次のエラーが発生します。

com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of com.graybar.utilities.ups.beans.Address: no String-argument constructor/factory method to deserialize from String value ('')

この問題が発生しているWebアプリケーションは、AngularJSフロントエンドを使用したSpring MVCアプリケーションですが、はるかに小さいすべてのJavaプログラムで問題を再現できます。ここに私のBeanを示します。

Shipment.Java

@JsonIgnoreProperties(ignoreUnknown = true)
public class Shipment {
    @JsonProperty("Activity")
    private ArrayList<Activity> activity;
    public ArrayList<Activity> getActivity() {
        return activity;
    }
    public void setActivity(ArrayList<Activity> activity) {
        this.activity = activity;
    }
}

Activity.Java

@JsonIgnoreProperties(ignoreUnknown = true)
public class Activity {
    @JsonProperty("ActivityLocation")
    private ArrayList<ActivityLocation> activityLocation;
    public ArrayList<ActivityLocation> getActivityLocation() {
        return activityLocation;
    }
    public void setActivityLocation(ArrayList<ActivityLocation> activityLocation) {
        this.activityLocation = activityLocation;
    }
}

ActivityLocation.Java

@JsonIgnoreProperties(ignoreUnknown = true)
public class ActivityLocation {
    @JsonProperty("Address")
    private Address address;
    public Address getAddress() {
        return address;
    }
    public void setAddress(Address address) {
        this.address = address;
    }
}

アドレス.Java

@JsonIgnoreProperties(ignoreUnknown = true)
public class Address {
    @JsonProperty("City")
    private String city;
    @JsonProperty("StateProvinceCode")
    private String stateProvinceCode;
    @JsonProperty("CountryCode")
    private String countryCode;
    public String getCity() {
        return city;
    }
    public void setCity(String city) {
        this.city = city;
    }
    public String getCountryCode() {
        return countryCode;
    }
    public void setCountryCode(String countryCode) {
        this.countryCode = countryCode;
    }
    public String getStateProvinceCode() {
        return stateProvinceCode;
    }
    public void setStateProvinceCode(String stateProvinceCode) {
        this.stateProvinceCode = stateProvinceCode;
    }
}

以下は、jsonを適切にマッピングできるコードです。

public static void main(String[] args) {
    String jsonMessage = "" +
        "{" + 
        "   \"Activity\": [{ " +
        "       \"ActivityLocation\": { " +
        "           \"Address\": { " +
        "               \"City\": \"Hana\", " +
        "               \"StateProvinceCode\": \"Hi\", " +
        "               \"CountryCode\": \"US\" " +
        "           } " +
        "       } " +
        "   }, " +
        "   { " +
        "       \"ActivityLocation\": { " +
        "           \"Address\": { " +
        "               \"City\": \"Honolulu\", " +
        "               \"StateProvinceCode\": \"Hi\", " +
        "               \"CountryCode\": \"US\" " +
        "           } " +
        "       } " +
        "   }] " +
    "} ";

    try {
        ObjectMapper mapper = new ObjectMapper();
        mapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);

        Shipment shipment = mapper.readValue(jsonMessage, Shipment.class);
        System.out.println("shipment.toString = " + shipment.toString());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

jsonMessage varのデータを調整するときは、上記のエラーが発生したときです。

    "{" + 
    "   \"Activity\": [{ " +
    "       \"ActivityLocation\": { " +
    "           \"Address\": { " +
    "               \"City\": \"Hana\", " +
    "               \"StateProvinceCode\": \"Hi\", " +
    "               \"CountryCode\": \"US\" " +
    "           } " +
    "       } " +
    "   }, " +
    "   { " +
    "       \"ActivityLocation\": { " +
    "           \"Address\": \"\" " +
    "           } " +
    "       } " +
    "   }] " +
    "} ";

したがって、jsonを次のように変更すると問題が発生します。

{
    "ActivityLocation": { 
        "Address": {
            "City": "Honolulu", 
            "StateProvinceCode": "Hi", 
            "CountryCode": "US"
        }
    }
}]

これに:

{
"ActivityLocation": {
     "Address": ""
    }
}

Address Beanの値を送信する代わりに、空の文字列を取得しています。残念ながら、私は第三者からデータを受信して​​おり、受信したデータを制御できません。

これを処理するために追加する必要がある注釈はありますか?

43
Stephen

mapper.configure(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true)を設定してみてください

または

mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);

ジャクソンのバージョンによって異なります。

35
Abhijit Sarkar

私が誤って電話していたときにこれを持っていました

mapper.convertValue(...)

の代わりに

mapper.readValue(...)

したがって、引数が同じで、IDEは多くのものを見つけることができるため、正しいメソッドを呼び出すことを確認してください

27

この例外は、「{…}」のようなオブジェクトの説明ではなく、文字列「\」\からオブジェクト「Address」を逆シリアル化しようとしていることを示しています。デシリアライザは、文字列引数を持つアドレスのコンストラクタを見つけることができません。このエラーを回避するには、 ""を{}に置き換える必要があります。

0
papaRomik