【问题标题】:Lombok + Jackson => MismatchedInputExceptionLombok + Jackson => MismatchedInputException
【发布时间】:2019-06-24 22:45:54
【问题描述】:

我有一个PSQL 表,其中一列包含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();

我总是遇到异常:

原因:com.fasterxml.jackson.databind.exc.MismatchedInputException:无法构造 my.package.model.User$UserAddress$UserAddressBuilder 的实例(尽管至少存在一个 Creator):没有 String-argument 构造函数/工厂方法可以从 String 值反序列化('" {\"street\":\"Some Street\",\"house_number\":\"Some House Number\"}')

由于字段匹配,我无法找到此问题的根源,不是吗? 我也尝试了不使用@Builder 的方法,并改用@Data、@AllArgsConstructor 和@NoArgsConstructor。

当使用readValue 而不是convertValue 时,我得到了相同的结果

【问题讨论】:

  • 错误非常明确,您应该有一个构造函数,该构造函数将要反序列化的字符串作为构建器类中的参数。
  • 我不认为我明白你的意思。我从这里得到了答案并实现了它:stackoverflow.com/questions/39381474/…
  • 你应该使用mapper.readValue(),而不是convertValue()。
  • 我已经试过了。结果相同。
  • 你的 UserAddressBuilder 类没有构造函数?

标签: java jackson lombok


【解决方案1】:

正如在 cmets 中提到的使用

.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)
抛出 IllegalArgumentException

从给定值到给定值类型的实例进行两步转换的便捷方法。 这相当于首先将给定值序列化为 JSON,然后将 JSON 数据绑定到给定类型的值,但可以在未完全序列化为 JSON 的情况下执行。相同的转换器(序列化器、反序列化器)将用于数据绑定,这意味着相同的对象映射器配置工作

readValue 用于从字符串、流、读取器读取对​​象值。使用convertValue(..),您可能需要定义转换器,但在您的情况下不需要。

【讨论】:

  • 我不明白为什么,但这解决了问题。我不明白MismatchedInputException 。
猜你喜欢
  • 1970-01-01
  • 2021-01-25
  • 2019-09-17
  • 1970-01-01
  • 2018-07-16
  • 2021-02-18
  • 2019-09-16
  • 1970-01-01
  • 2018-07-22
相关资源
最近更新 更多