com.fasterxml.jackson.datatype.joda.deser.DateTimeDeserializer类没有默认的(无参)构造函数。

7

当我尝试使用restangular进行post请求时,出现了以下错误 -“Class com.fasterxml.jackson.datatype.joda.deser.DateTimeDeserializer没有默认(无参)构造函数”。 当我调用该方法时,它会进入错误块。

Restangular.all('tests').post($scope.test).then(function (data) {
                    $scope.test.id = data.id;
                    $location.path($location.path() + data.id).replace();
                }, function (error) {
                    $scope.exceptionDetails = validationMapper(error);
                });

我正在使用 jackson-datatype-joda - 2.6.5

在这个方法中使用的实体类如下 -

@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
@Entity
@Table(name = "Test")
@EqualsAndHashCode(of = "id", callSuper = false)
@ToString(exclude = {"keywords", "relevantObjectIds"})
public class Test {
    @Id
    @Column(unique = true, length = 36)
    private String id;

    @NotBlank
    @NotNull
    private String name;

    @Transient
    private List<Testabc> Testabcs = new ArrayList<>();

}

上述实体Testabc类中使用的实体类如下所示:
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
@Slf4j
@Entity
@Table(name = "Test_abc")
@EqualsAndHashCode(of = "id", callSuper = false)
public class Testabc{
    @Id
    @Column(unique = true, length = 36)
    @NotNull
    private String id = UUID.randomUUID().toString();

 @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime")
    @JsonDeserialize(using = DateTimeDeserializer.class)
    @JsonSerialize(using = DateTimeSerializer.class)
    private DateTime createdOn;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "Id")
    @NotNull
    private t1 pid;

    private long originalSize;
}

最后,我请求创建测试数据的资源类是 -
@ApiOperation(value = "Create new Test", notes = "Create a new Test and return with its unique id", response = Test.class)
    @POST
    @Timed
    public Test create(Test newInstance) {
        return super.create(newInstance);
    }

我尝试在实体类上添加@JsonIgnoreProperties(ignoreUnknown = true)注解,但它没有起作用。有人可以帮忙解决这个问题吗?

可能是 joda.time.DateTime 反序列化错误 的重复问题。 - Morfic
没有重复。 - Geetanjali Jain
1
这是否意味着链接问题答案的解释和建议的 mapper.registerModule(new JodaModule()); 解决方案对你无效? - Morfic
这个链接(https://dev59.com/g5bfa4cB1Zd3GeqPsVpL)建议使用注解或上述帮助,而我想只用注解来完成这项工作。我需要在注解中使用mapper.registerModule(new JodaModule());吗? - Geetanjali Jain
1
两个解决方案都指出DateTimeDeserializer没有无参构造函数,这确实是你的问题所在。如果你想只使用注解,你可以简单地扩展它并添加一个调用必要参数的无参构造函数。 - Morfic
2个回答

5

查看DateTimeDeserializer的最新源代码,您可以很容易地发现它没有无参数构造函数,这似乎是框架所需的。 这也在两个相关问题中指出:joda.time.DateTime deserialization errorJackson,Retrofit,JodaTime deserialization

由于您只想使用基于注释的解决方案,一个可能的解决方法是创建自己的反序列化器,它扩展了DateTimeDeserializer并提供了一个无参构造函数。

1)MyDateTimeSerializer

import com.fasterxml.jackson.datatype.joda.cfg.FormatConfig;
import com.fasterxml.jackson.datatype.joda.deser.DateTimeDeserializer;
import org.joda.time.DateTime;

public class MyDateTimeDeserializer extends DateTimeDeserializer {
    public MyDateTimeDeserializer() {
        // no arg constructor providing default values for super call
        super(DateTime.class, FormatConfig.DEFAULT_DATETIME_PARSER);
    }
}

2) 使用自定义反序列化器的 AClass

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.joda.ser.DateTimeSerializer;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;

public class AClass {

    @JsonSerialize(using = DateTimeSerializer.class) // old serializer
    @JsonDeserialize(using = MyDateTimeDeserializer.class) // new deserializer
    private DateTime createdOn = DateTime.now(DateTimeZone.UTC); // some dummy data for the sake of brevity

    public DateTime getCreatedOn() {
        return createdOn;
    }

    public void setCreatedOn(DateTime createdOn) {
        this.createdOn = createdOn;
    }
}

3) 单元测试

import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.Test;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;

public class ATest {
    @Test
    public void testSomeMethod() throws Exception {
        // Jackson object mapper to test serialization / deserialization
        ObjectMapper objectMapper = new ObjectMapper();

        // our object
        AClass initialObject = new AClass();

        // serialize it
        String serializedObject = objectMapper.writeValueAsString(initialObject);

        // deserialize it
        AClass deserializedObject = objectMapper.readValue(serializedObject, AClass.class);

        // check that the dates are equal (no equals implementation on the class itself...)
        assertThat(deserializedObject.getCreatedOn(), is(equalTo(initialObject.getCreatedOn())));
    }
}

谢谢,但它不起作用,仍然出现相同的错误。 - Geetanjali Jain
@Geetanjali 虽然这是可能的,但你改变了某些东西后得到相同的异常的可能性非常小,因为这意味着你的修改没有任何影响。你能否请清理你的工作区/输出文件夹,重新构建你的应用程序,然后重试并分享异常消息和堆栈跟踪? - Morfic
谢谢您的回复,但我已经尝试了您的建议,并确保我已经构建和清理了应用程序。还有一件事就是我没有任何堆栈跟踪,因为代码在进入Java代码之前就会中断,它只是调用Restangular的错误块,即“Class com.fasterxml.jackson.datatype.joda.deser.DateTimeDeserializer没有默认(无参)构造函数”。 - Geetanjali Jain
@Geetanjali 如果您已经在实体中将 DateTimeDeserializer 替换为 MyDateTimeDeserializer,但仍然遇到相同的异常,则问题必须出现在其他地方。在这种情况下,您能否在 GitHub 或类似平台上分享后端的 SSCCE 代码? - Morfic
抱歉,我不能分享我的代码,因为它是客户的代码。 - Geetanjali Jain
@Geetanjali 当然,这是正常和可以理解的。尽管如此,这并不是 SSCCE 的含义。相反,它意味着从头开始创建最简单的示例,以复制您的问题,同时省略任何敏感信息。这样我们就可以调试和发现您可能忽略的任何异常情况。否则,我们只能继续猜测可能出了什么问题,使事情变得非常困难。 - Morfic

1

这个反序列化器从来没有被设计用于注释,并且正如其他人所提到的,也不能。通常情况下,您应该只需添加/注册JodaModule,然后序列化程序/反序列化程序会按预期添加。

我不确定为什么您不想走这条路线;值得扩展的是为什么这种解决方案(或通过自定义模块注册的DateTimeDeserializer.forType(ReadableDateTime.class)获得的反序列化器)不适用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接