从对象转换为 AWS Kinesis -> Java 无法从 VALUE_NUMBER_FLOAT 令牌中反序列化 `java.util.Date` 的实例
Convert from object to AWS Kinesis -> Java Cannot deserialize instance of `java.util.Date` out of VALUE_NUMBER_FLOAT token
我正在使用 AWS lambda 函数以动态获取 SNS 事件或 Kinesis 事件,为此,在我的 lambda 函数中我将对象作为参数:
@Override
public GatewayResponse handleRequest(final Object object, Context context)
然后,我使用 Jackson 将其动态转换为 SNS 或 Kinesis:
public static SNSEvent convertObjectToSNSEvent(Object object) {
return objectMapper.convertValue(object, SNSEvent.class);
}
public static KinesisEvent convertToKinesisEvent(Object object) {
return objectMapper.convertValue(object, KinesisEvent.class);
}
问题是,当我使用 convertToKinesisEvent
函数时,我得到:
java.lang.IllegalArgumentException: Cannot deserialize instance of `java.util.Date` out of VALUE_NUMBER_FLOAT token
SNSEvent 转换工作正常,但 Kinesis 没有,我意识到这是因为在 Kinesis Json 中,时间戳(approximateArrivalTimestamp 字段)用小数表示:
{
"Records": [
{
"kinesis": {
"partitionKey": "partitionKey-03",
"kinesisSchemaVersion": "1.0",
"data": "eyJpZCI6MjY2MjU4NSwiZGVzY3JpcHRpb24iOiJUZXN0IFBheWxvYWQifQ==",
"sequenceNumber": "49545115243490985018280067714973144582180062593244200961",
"approximateArrivalTimestamp": 1.57538737506E9
},
"eventSource": "aws:kinesis",
"eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244200961",
"invokeIdentityArn": "arn:aws:iam::EXAMPLE",
"eventVersion": "1.0",
"eventName": "aws:kinesis:record",
"eventSourceARN": "arn:aws:kinesis:EXAMPLE",
"awsRegion": "us-east-1"
}
]
}
如果我在时间戳中使用整数执行相同的代码,它工作正常:
{
"Records": [
{
"kinesis": {
"partitionKey": "partitionKey-03",
"kinesisSchemaVersion": "1.0",
"data": "eyJpZCI6MjY2MjU4NSwiZGVzY3JpcHRpb24iOiJUZXN0IFBheWxvYWQifQ==",
"sequenceNumber": "49545115243490985018280067714973144582180062593244200961",
"approximateArrivalTimestamp": 11234432432
},
"eventSource": "aws:kinesis",
"eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244200961",
"invokeIdentityArn": "arn:aws:iam::EXAMPLE",
"eventVersion": "1.0",
"eventName": "aws:kinesis:record",
"eventSourceARN": "arn:aws:kinesis:EXAMPLE",
"awsRegion": "us-east-1"
}
]
}
这是完整的错误日志:
java.lang.IllegalArgumentException: Cannot deserialize instance of `java.util.Date` out of VALUE_NUMBER_FLOAT token
at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: com.amazonaws.services.lambda.runtime.events.KinesisEvent["Records"]->java.util.ArrayList[0]->com.amazonaws.services.lambda.runtime.events.KinesisEvent$KinesisEventRecord["kinesis"]->com.amazonaws.services.lambda.runtime.events.KinesisEvent$Record["approximateArrivalTimestamp"])
at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:3922)
at com.fasterxml.jackson.databind.ObjectMapper.convertValue(ObjectMapper.java:3853)
at util.JsonUtil.convertToKinesisEvent(JsonUtil.java:28)
at pojos.RecordsHandler.getMessages(RecordsHandler.java:38)
at handler.App.handleRequest(App.java:41)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at lambdainternal.EventHandlerLoader$PojoMethodRequestHandler.handleRequest(EventHandlerLoader.java:261)
at lambdainternal.EventHandlerLoader$PojoHandlerAsStreamHandler.handleRequest(EventHandlerLoader.java:178)
at lambdainternal.EventHandlerLoader.call(EventHandlerLoader.java:906)
at lambdainternal.AWSLambda.startRuntime(AWSLambda.java:341)
at lambdainternal.AWSLambda.<clinit>(AWSLambda.java:63)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at lambdainternal.LambdaRTEntry.main(LambdaRTEntry.java:114)
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.util.Date` out of VALUE_NUMBER_FLOAT token
有人知道发生了什么事吗?
--更新--
依赖项:
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.squareup.retrofit2/retrofit -->
<dependency>
<groupId>com.squareup.retrofit2</groupId>
<artifactId>retrofit</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>com.squareup.retrofit2</groupId>
<artifactId>converter-jackson</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.10.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.datatype/jackson-datatype-joda -->
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.amazonaws/aws-lambda-java-events -->
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-events</artifactId>
<version>2.2.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk -->
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>1.11.685</version>
</dependency>
</dependencies>
谢谢
好的,所以我最后做的是将我的自定义解串器添加到 Jackson 以解决问题:
public class TimestampDeserializer extends JsonDeserializer<Date> {
@Override
public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(jsonParser.getValueAsLong());
return calendar.getTime();
}
}
然后添加自定义序列化程序
public class TimestampSerializer extends JsonSerializer<Date> {
@Override
public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeString(date.toString());
}
}
然后将其添加到 Jackson 并成功,我不知道是否有其他解决方案但是它实现了我的目标
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(Date.class, new TimestampSerializer());
module.addDeserializer(Date.class, new TimestampDeserializer());
objectMapper.registerModule(module);
问题是 Lambda 服务为了将一些请求转换为 Java 对象而进行了额外的工作。
这是为了处理不符合正常 Java 命名标准的请求类型。
您可以找到完成这项工作的代码 - aws-lambda-java-serialization
我正在使用 AWS lambda 函数以动态获取 SNS 事件或 Kinesis 事件,为此,在我的 lambda 函数中我将对象作为参数:
@Override
public GatewayResponse handleRequest(final Object object, Context context)
然后,我使用 Jackson 将其动态转换为 SNS 或 Kinesis:
public static SNSEvent convertObjectToSNSEvent(Object object) {
return objectMapper.convertValue(object, SNSEvent.class);
}
public static KinesisEvent convertToKinesisEvent(Object object) {
return objectMapper.convertValue(object, KinesisEvent.class);
}
问题是,当我使用 convertToKinesisEvent
函数时,我得到:
java.lang.IllegalArgumentException: Cannot deserialize instance of `java.util.Date` out of VALUE_NUMBER_FLOAT token
SNSEvent 转换工作正常,但 Kinesis 没有,我意识到这是因为在 Kinesis Json 中,时间戳(approximateArrivalTimestamp 字段)用小数表示:
{
"Records": [
{
"kinesis": {
"partitionKey": "partitionKey-03",
"kinesisSchemaVersion": "1.0",
"data": "eyJpZCI6MjY2MjU4NSwiZGVzY3JpcHRpb24iOiJUZXN0IFBheWxvYWQifQ==",
"sequenceNumber": "49545115243490985018280067714973144582180062593244200961",
"approximateArrivalTimestamp": 1.57538737506E9
},
"eventSource": "aws:kinesis",
"eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244200961",
"invokeIdentityArn": "arn:aws:iam::EXAMPLE",
"eventVersion": "1.0",
"eventName": "aws:kinesis:record",
"eventSourceARN": "arn:aws:kinesis:EXAMPLE",
"awsRegion": "us-east-1"
}
]
}
如果我在时间戳中使用整数执行相同的代码,它工作正常:
{
"Records": [
{
"kinesis": {
"partitionKey": "partitionKey-03",
"kinesisSchemaVersion": "1.0",
"data": "eyJpZCI6MjY2MjU4NSwiZGVzY3JpcHRpb24iOiJUZXN0IFBheWxvYWQifQ==",
"sequenceNumber": "49545115243490985018280067714973144582180062593244200961",
"approximateArrivalTimestamp": 11234432432
},
"eventSource": "aws:kinesis",
"eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244200961",
"invokeIdentityArn": "arn:aws:iam::EXAMPLE",
"eventVersion": "1.0",
"eventName": "aws:kinesis:record",
"eventSourceARN": "arn:aws:kinesis:EXAMPLE",
"awsRegion": "us-east-1"
}
]
}
这是完整的错误日志:
java.lang.IllegalArgumentException: Cannot deserialize instance of `java.util.Date` out of VALUE_NUMBER_FLOAT token
at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: com.amazonaws.services.lambda.runtime.events.KinesisEvent["Records"]->java.util.ArrayList[0]->com.amazonaws.services.lambda.runtime.events.KinesisEvent$KinesisEventRecord["kinesis"]->com.amazonaws.services.lambda.runtime.events.KinesisEvent$Record["approximateArrivalTimestamp"])
at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:3922)
at com.fasterxml.jackson.databind.ObjectMapper.convertValue(ObjectMapper.java:3853)
at util.JsonUtil.convertToKinesisEvent(JsonUtil.java:28)
at pojos.RecordsHandler.getMessages(RecordsHandler.java:38)
at handler.App.handleRequest(App.java:41)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at lambdainternal.EventHandlerLoader$PojoMethodRequestHandler.handleRequest(EventHandlerLoader.java:261)
at lambdainternal.EventHandlerLoader$PojoHandlerAsStreamHandler.handleRequest(EventHandlerLoader.java:178)
at lambdainternal.EventHandlerLoader.call(EventHandlerLoader.java:906)
at lambdainternal.AWSLambda.startRuntime(AWSLambda.java:341)
at lambdainternal.AWSLambda.<clinit>(AWSLambda.java:63)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at lambdainternal.LambdaRTEntry.main(LambdaRTEntry.java:114)
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.util.Date` out of VALUE_NUMBER_FLOAT token
有人知道发生了什么事吗?
--更新-- 依赖项:
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.squareup.retrofit2/retrofit -->
<dependency>
<groupId>com.squareup.retrofit2</groupId>
<artifactId>retrofit</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>com.squareup.retrofit2</groupId>
<artifactId>converter-jackson</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.10.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.datatype/jackson-datatype-joda -->
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
<version>2.10.1</version>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.amazonaws/aws-lambda-java-events -->
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-events</artifactId>
<version>2.2.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk -->
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk</artifactId>
<version>1.11.685</version>
</dependency>
</dependencies>
谢谢
好的,所以我最后做的是将我的自定义解串器添加到 Jackson 以解决问题:
public class TimestampDeserializer extends JsonDeserializer<Date> {
@Override
public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(jsonParser.getValueAsLong());
return calendar.getTime();
}
}
然后添加自定义序列化程序
public class TimestampSerializer extends JsonSerializer<Date> {
@Override
public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeString(date.toString());
}
}
然后将其添加到 Jackson 并成功,我不知道是否有其他解决方案但是它实现了我的目标
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(Date.class, new TimestampSerializer());
module.addDeserializer(Date.class, new TimestampDeserializer());
objectMapper.registerModule(module);
问题是 Lambda 服务为了将一些请求转换为 Java 对象而进行了额外的工作。
这是为了处理不符合正常 Java 命名标准的请求类型。
您可以找到完成这项工作的代码 - aws-lambda-java-serialization