龙目岛 + 杰克逊 => MismatchedInputException
Lombok + Jackson => MismatchedInputException
我有一个 PSQL
table,其中一列包含 jsonb
数据:
CREATE TABLE IF NOT EXISTS user (
user_name VARCHAR(255) NOT NULL,
user_email VARCHAR(255) NOT NULL,
user_address jsonb NOT NULL
)
我有以下java object
:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import lombok.Builder;
import lombok.Value;
@Value
@Builder
public class User {
private String userName;
private String userEmail;
private UserAddress address;
@Value
@Builder
@JsonDeserialize(builder = UserAddress.UserAddressBuilder.class)
public static class UserAddress {
@JsonProperty("street")
private String street;
@JsonProperty("house_number")
private String houseNumber;
@JsonPOJOBuilder(withPrefix = "")
public static class UserAddressBuilder {
private String street = null;
private String houseNumber = null;
public UserAddressBuilder street(String street) {
this.street = street;
return this;
}
public UserAddressBuilder houseNumber(String houseNumber) {
this.houseNumber = houseNumber;
return this;
}
}
}
}
当我现在从 ResultSet
构建 User
时:
return User.builder()
.userName(rs.getString(SqlConstants.TableUser.USER_NAME))
.userEmail(rs.getString(SqlConstants.TableUser.USER_EMAIL))
.userAddress(mapper.convertValue(rs.getString(SqlConstants.TableUser.USER_ADDRESS), User.UserAddress.class))
.build();
我总是遇到异常:
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of my.package.model.User$UserAddress$UserAddressBuilder
(although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('"{\"street\":\"Some Street\",\"house_number\":\"Some House Number\"}')
我找不到这个问题的根源,因为这些字段是匹配的,不是吗?
我也尝试了不使用 @Builder
的方法,而是使用了 @Data
、@AllArgsConstructor
和 @NoArgsConstructor
。
我使用 readValue
而不是 convertValue
得到相同的结果
如评论中所述,使用
.userAddress(mapper.readValue(rs.getString(SqlConstants.TableUser.USER_ADDRESS),
User.UserAddress.class))
应该可以正常工作,至少对我来说是这样。然而在那个改变之后你可能 运行 变成:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "house_number" ...
(而不是原来的错误)将通过对 UserAddressBuilder
:
的小改动来修复
@JsonProperty("house_number") // this is also needed to map correctly
public UserAddressBuilder houseNumber(String houseNumber) { ...
来自Javadoc:
public T convertValue(Object fromValue, Class toValueType)
throws IllegalArgumentException
Convenience method for doing two-step conversion from given value, into instance of given value type. This is functionality equivalent to first serializing given value into JSON, then binding JSON data into value of given type, but may be executed without fully serializing into JSON. Same converters (serializers, deserializers) will be used as for data binding, meaning same object mapper configuration works
而 readValue
用于从字符串、流、reader 读取到对象值。使用 convertValue(..)
您可能需要定义转换器,但在您的情况下不需要。
我有一个 PSQL
table,其中一列包含 jsonb
数据:
CREATE TABLE IF NOT EXISTS user (
user_name VARCHAR(255) NOT NULL,
user_email VARCHAR(255) NOT NULL,
user_address jsonb NOT NULL
)
我有以下java object
:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import lombok.Builder;
import lombok.Value;
@Value
@Builder
public class User {
private String userName;
private String userEmail;
private UserAddress address;
@Value
@Builder
@JsonDeserialize(builder = UserAddress.UserAddressBuilder.class)
public static class UserAddress {
@JsonProperty("street")
private String street;
@JsonProperty("house_number")
private String houseNumber;
@JsonPOJOBuilder(withPrefix = "")
public static class UserAddressBuilder {
private String street = null;
private String houseNumber = null;
public UserAddressBuilder street(String street) {
this.street = street;
return this;
}
public UserAddressBuilder houseNumber(String houseNumber) {
this.houseNumber = houseNumber;
return this;
}
}
}
}
当我现在从 ResultSet
构建 User
时:
return User.builder()
.userName(rs.getString(SqlConstants.TableUser.USER_NAME))
.userEmail(rs.getString(SqlConstants.TableUser.USER_EMAIL))
.userAddress(mapper.convertValue(rs.getString(SqlConstants.TableUser.USER_ADDRESS), User.UserAddress.class))
.build();
我总是遇到异常:
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of
my.package.model.User$UserAddress$UserAddressBuilder
(although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('"{\"street\":\"Some Street\",\"house_number\":\"Some House Number\"}')
我找不到这个问题的根源,因为这些字段是匹配的,不是吗?
我也尝试了不使用 @Builder
的方法,而是使用了 @Data
、@AllArgsConstructor
和 @NoArgsConstructor
。
我使用 readValue
而不是 convertValue
如评论中所述,使用
.userAddress(mapper.readValue(rs.getString(SqlConstants.TableUser.USER_ADDRESS),
User.UserAddress.class))
应该可以正常工作,至少对我来说是这样。然而在那个改变之后你可能 运行 变成:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "house_number" ...
(而不是原来的错误)将通过对 UserAddressBuilder
:
@JsonProperty("house_number") // this is also needed to map correctly
public UserAddressBuilder houseNumber(String houseNumber) { ...
来自Javadoc:
public T convertValue(Object fromValue, Class toValueType)
throws IllegalArgumentExceptionConvenience method for doing two-step conversion from given value, into instance of given value type. This is functionality equivalent to first serializing given value into JSON, then binding JSON data into value of given type, but may be executed without fully serializing into JSON. Same converters (serializers, deserializers) will be used as for data binding, meaning same object mapper configuration works
而 readValue
用于从字符串、流、reader 读取到对象值。使用 convertValue(..)
您可能需要定义转换器,但在您的情况下不需要。