복붙노트

[SPRING] String 값 ( '')을 역 직렬화 할 문자열 인수 생성자 / 팩토리 메소드

SPRING

String 값 ( '')을 역 직렬화 할 문자열 인수 생성자 / 팩토리 메소드

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 ('')

이 문제가 발생하는 웹 응용 프로그램은 AngularJS 프런트 엔드를 사용하는 Spring MVC 응용 프로그램이지만 훨씬 작은 모든 Java 프로그램으로이 문제를 복제 할 수 있습니다. 여기 내 콩이있다.

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;
    }
}

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에서 데이터를 조정할 때, 위에서 언급 한 오류가 발생합니다.

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

그래서 문제는 json을 다음과 같이 변경할 때 발생합니다.

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

이에:

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

내 주소 bean에 값을 보내는 대신 빈 문자열 만 가져옵니다. 안타깝게도 타사로부터 제 데이터를 받고 있으며받은 데이터를 제어 할 수 없습니다.

이것을 처리 할 수 ​​있도록 주석을 추가해야합니까?

해결법

  1. ==============================

    1.mapper.configure를 설정해보십시오 (DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true).

    mapper.configure를 설정해보십시오 (DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true).

    또는

    mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
    

    잭슨 버전에 따라 다릅니다.

  2. ==============================

    2.

    mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
    

    내 코드는 위의 대답처럼 잘 작동합니다. 그 이유는 jackson의 json이 컨트롤러에서 보낸 json과 다르다는 것입니다.

    String test1= mapper.writeValueAsString(result1);
    

    그리고 json은 비슷합니다 (정상적으로 비 직렬화 될 수 있습니다).

    {"code":200,"message":"god","data":[{"nics":null,"status":null,"desktopOperatorType":null,"marker":null,"user_name":null,"user_group":null,"user_email":null,"product_id":null,"image_id":null,"computer_name":"AAAA","desktop_id":null,"created":null,"ip_address":null,"security_groups":null,"root_volume":null,"data_volumes":null,"availability_zone":null,"ou_name":null,"login_status":null,"desktop_ip":null,"ad_id":null},{"nics":null,"status":null,"desktopOperatorType":null,"marker":null,"user_name":null,"user_group":null,"user_email":null,"product_id":null,"image_id":null,"computer_name":"BBBB","desktop_id":null,"created":null,"ip_address":null,"security_groups":null,"root_volume":null,"data_volumes":null,"availability_zone":null,"ou_name":null,"login_status":null,"desktop_ip":null,"ad_id":null}]}
    

    그러나 json은 다음과 같은 또 다른 서비스를 보낸다.

    {"code":200,"message":"查询桌面列表成功","data":[{"nics":"","status":"","metadata":"","desktopOperatorType":"","marker":"","user_name":"csrgzbsjy","user_group":"ADMINISTRATORS","user_email":"","product_id":"","image_id":"","computer_name":"B-jiegou-all-15","desktop_id":"6360ee29-eb82-416b-aab8-18ded887e8ff","created":"2018-11-12T07:45:15.000Z","ip_address":"192.168.2.215","security_groups":"","root_volume":"","data_volumes":"","availability_zone":"","ou_name":"","login_status":"","desktop_ip":"","ad_id":""},{"nics":"","status":"","metadata":"","desktopOperatorType":"","marker":"","user_name":"glory_2147","user_group":"ADMINISTRATORS","user_email":"","product_id":"","image_id":"","computer_name":"H-pkpm-all-357","desktop_id":"709164e4-d3e6-495d-9c1e-a7b82e30bc83","created":"2018-11-09T09:54:09.000Z","ip_address":"192.168.2.235","security_groups":"","root_volume":"","data_volumes":"","availability_zone":"","ou_name":"","login_status":"","desktop_ip":"","ad_id":""}]}
    

    시작하지 않고 매개 변수를 처리 할 때 차이점을 확인할 수 있습니다. 조심해

  3. from https://stackoverflow.com/questions/45110371/no-string-argument-constructor-factory-method-to-deserialize-from-string-value by cc-by-sa and MIT license