配置 Java AWS Lambda 使用的对象映射器
Configure Objectmapper used by Java AWS Lambda
我正在尝试开发一个由来自 SQS 的事件触发的 AWS Lambda 函数。
我正在使用 spring-cloud-function-adapter-aws(版本 1.0.0.RELEASE),特别是 SpringBootRequestHandler.
但是,正在使用的 ObjectMapper 区分大小写,因此无法成功转换来自 SQS 的 Json。
SQS 发布了以下 Json,我特别遇到问题的是 Records 字段。
{
"Records": [
{
"body": "Hello from SQS!",
"receiptHandle": "MessageReceiptHandle",
"md5OfBody": "7b270e59b47ff90a553787216d55d91d",
"eventSourceARN": "arn:aws:sqs:eu-west-1:123456789012:MyQueue",
"eventSource": "aws:sqs",
"awsRegion": "eu-west-1",
"messageId": "19dd0b57-b21e-4ac1-bd88-01bbb068cb78",
"attributes": {
"ApproximateFirstReceiveTimestamp": "1523232000001",
"SenderId": "123456789012",
"ApproximateReceiveCount": "1",
"SentTimestamp": "1523232000000"
},
"messageAttributes": {}
}
]
}
我已经尝试了这个问题中的建议,但无济于事。 Configuring ObjectMapper in Spring
在我的 POJO 中,我还添加了以下注释,但它在 Lambda 之外也不起作用。
@JsonProperty("Records")
private List<SqsRecord> Records;
如有任何帮助,我们将不胜感激。
我的 Lambda 处理程序定义为:
public class SqsEventHandler extends SpringBootRequestHandler<SqsEvent, String> {}
POJO 定义为:
public class SqsEvent {
@JsonProperty("Records")
private List<SqsRecord> records;
@Data
public class SqsRecord {
private String body;
private String receiptHandle;
private String md5OfBody;
private String eventSourceARN;
private String eventSource;
private String awsRegion;
private String messageId;
}
}
我希望示例消息中的 Json 能够被 ObjectMapper 读取,但是字段 "records" 为空。
我们的很多 AWS 服务都遇到了这个问题。
您必须像这样定义一个新的映射器:
SQSMixin :
private static interface SQSEventMixin {
public static final String ATTRIBUTES = "attributes";
public static final String AWS_REGION = "awsRegion";
public static final String BODY = "body";
public static final String EVENT_SOURCE = "eventSource";
public static final String EVENT_SOURCE_ARN = "eventSourceARN";
public static final String MD5_OF_BOBY = "md5OfBody";
public static final String MD5_OF_MESSAGE_ATTRIBUTES = "md5OfMessageAttributes";
public static final String MESSAGE_ID = "messageId";
public static final String RECEIPT_HANDLE = "receiptHandle";
@JsonProperty(value = "Records")
public List<?> getRecords();
static interface MessageMixin {
@JsonProperty(ATTRIBUTES)
public String getAttributes();
@JsonProperty(ATTRIBUTES)
public void setAttributes(String attributes);
@JsonProperty(AWS_REGION)
public String getAwsRegion();
@JsonProperty(AWS_REGION)
public void setAwsRegion(String awsRegion);
@JsonProperty(BODY)
public Object getBody();
@JsonProperty(BODY)
public void setBody(Object body);
@JsonProperty(EVENT_SOURCE)
public String getEventSource();
@JsonProperty(EVENT_SOURCE)
public void setEventSource(String eventSource);
@JsonProperty(EVENT_SOURCE_ARN)
public String getEventSourceArn();
@JsonProperty(EVENT_SOURCE_ARN)
public void setEventSourceArn(String eventSourceArn);
@JsonProperty(MD5_OF_BOBY)
public String getMd5OfBody();
@JsonProperty(MD5_OF_BOBY)
public void setMd5OfBody(String md5OfBody);
@JsonProperty(MD5_OF_MESSAGE_ATTRIBUTES)
public String getMd5OfMessageAttributes();
@JsonProperty(MD5_OF_MESSAGE_ATTRIBUTES)
public void setMd5OfMessageAttributes(String md5OfMessageAttributes);
@JsonProperty(MESSAGE_ID)
public String getMessageId();
@JsonProperty(MESSAGE_ID)
public void setMessageId(String messageId);
@JsonProperty(RECEIPT_HANDLE)
public String getReceiptHandle();
@JsonProperty(RECEIPT_HANDLE)
public void setReceiptHandle(String receiptHandle);
}
}
记录策略:
private static class UpperCaseRecordsPropertyNamingStrategy extends PropertyNamingStrategy.PropertyNamingStrategyBase {
private static final long serialVersionUID = 1L;
@Override
public String translate(String propertyName) {
if (propertyName.equals("records")) {
return "Records";
}
return propertyName;
}
}
日期格式化程序:
private static final DateTimeFormatter dateTimeFormatter = ISODateTimeFormat.dateTime()
.withZone(new FixedDateTimeZone("GMT", "GMT", 0, 0));
private static class DateTimeMapperModule extends SimpleModule {
private static final long serialVersionUID = 1L;
public DateTimeMapperModule() {
super("DateTimeMapperModule");
super.addSerializer(DateTime.class, new DateTimeSerializer());
super.addDeserializer(DateTime.class, new DateTimeDeserializer());
}
}
private static class DateTimeSerializer extends JsonSerializer<DateTime> {
@Override
public void serialize(DateTime value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeString(dateTimeFormatter.print(value));
}
}
private static class DateTimeDeserializer extends JsonDeserializer<DateTime> {
@Override
public DateTime deserialize(JsonParser parser, DeserializationContext context) throws IOException {
return dateTimeFormatter.parseDateTime(parser.getText());
}
}
并声明您的映射器:
ObjectMapper mapper = new ObjectMapper();
mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
mapper.setPropertyNamingStrategy(new UpperCaseRecordsPropertyNamingStrategy());
mapper.registerModule(new DateTimeMapperModule());
mapper.addMixIn(SQSMessage.class, SQSEventMixin.MessageMixin.class);
SQSEvent request = mapper.convertValue(inputObject, SQSEvent.class);
我用更简单的方式解决了这个问题。
引用 https://docs.aws.amazon.com/lambda/latest/dg/java-handler-io-type-stream.html 并具体
if Lambda's serialization approach does not meet your needs, you can use the byte stream implementation
我现在直接使用 SpringBootStreamHandler,并且在我的 Spring 配置 class 中创建了一个包含所需配置选项的 ObjectMapper 实例:
@Bean
public ObjectMapper objectMapper() {
final ObjectMapper mapper = new ObjectMapper();
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return mapper;
}
已经有一个官方库支持这个:https://aws.amazon.com/blogs/opensource/testing-aws-lambda-functions-written-in-java/
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-tests</artifactId>
<version>1.0.0</version>
<scope>test</scope>
</dependency>
你的插件中也有 surefire:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</plugin>
</plugins>
</build>
示例:
SQSEvent input = EventLoader.loadEvent("/sqsEvent.json", SQSEvent.class);
我正在尝试开发一个由来自 SQS 的事件触发的 AWS Lambda 函数。
我正在使用 spring-cloud-function-adapter-aws(版本 1.0.0.RELEASE),特别是 SpringBootRequestHandler.
但是,正在使用的 ObjectMapper 区分大小写,因此无法成功转换来自 SQS 的 Json。
SQS 发布了以下 Json,我特别遇到问题的是 Records 字段。
{
"Records": [
{
"body": "Hello from SQS!",
"receiptHandle": "MessageReceiptHandle",
"md5OfBody": "7b270e59b47ff90a553787216d55d91d",
"eventSourceARN": "arn:aws:sqs:eu-west-1:123456789012:MyQueue",
"eventSource": "aws:sqs",
"awsRegion": "eu-west-1",
"messageId": "19dd0b57-b21e-4ac1-bd88-01bbb068cb78",
"attributes": {
"ApproximateFirstReceiveTimestamp": "1523232000001",
"SenderId": "123456789012",
"ApproximateReceiveCount": "1",
"SentTimestamp": "1523232000000"
},
"messageAttributes": {}
}
]
}
我已经尝试了这个问题中的建议,但无济于事。 Configuring ObjectMapper in Spring
在我的 POJO 中,我还添加了以下注释,但它在 Lambda 之外也不起作用。
@JsonProperty("Records")
private List<SqsRecord> Records;
如有任何帮助,我们将不胜感激。
我的 Lambda 处理程序定义为:
public class SqsEventHandler extends SpringBootRequestHandler<SqsEvent, String> {}
POJO 定义为:
public class SqsEvent {
@JsonProperty("Records")
private List<SqsRecord> records;
@Data
public class SqsRecord {
private String body;
private String receiptHandle;
private String md5OfBody;
private String eventSourceARN;
private String eventSource;
private String awsRegion;
private String messageId;
}
}
我希望示例消息中的 Json 能够被 ObjectMapper 读取,但是字段 "records" 为空。
我们的很多 AWS 服务都遇到了这个问题。 您必须像这样定义一个新的映射器:
SQSMixin :
private static interface SQSEventMixin {
public static final String ATTRIBUTES = "attributes";
public static final String AWS_REGION = "awsRegion";
public static final String BODY = "body";
public static final String EVENT_SOURCE = "eventSource";
public static final String EVENT_SOURCE_ARN = "eventSourceARN";
public static final String MD5_OF_BOBY = "md5OfBody";
public static final String MD5_OF_MESSAGE_ATTRIBUTES = "md5OfMessageAttributes";
public static final String MESSAGE_ID = "messageId";
public static final String RECEIPT_HANDLE = "receiptHandle";
@JsonProperty(value = "Records")
public List<?> getRecords();
static interface MessageMixin {
@JsonProperty(ATTRIBUTES)
public String getAttributes();
@JsonProperty(ATTRIBUTES)
public void setAttributes(String attributes);
@JsonProperty(AWS_REGION)
public String getAwsRegion();
@JsonProperty(AWS_REGION)
public void setAwsRegion(String awsRegion);
@JsonProperty(BODY)
public Object getBody();
@JsonProperty(BODY)
public void setBody(Object body);
@JsonProperty(EVENT_SOURCE)
public String getEventSource();
@JsonProperty(EVENT_SOURCE)
public void setEventSource(String eventSource);
@JsonProperty(EVENT_SOURCE_ARN)
public String getEventSourceArn();
@JsonProperty(EVENT_SOURCE_ARN)
public void setEventSourceArn(String eventSourceArn);
@JsonProperty(MD5_OF_BOBY)
public String getMd5OfBody();
@JsonProperty(MD5_OF_BOBY)
public void setMd5OfBody(String md5OfBody);
@JsonProperty(MD5_OF_MESSAGE_ATTRIBUTES)
public String getMd5OfMessageAttributes();
@JsonProperty(MD5_OF_MESSAGE_ATTRIBUTES)
public void setMd5OfMessageAttributes(String md5OfMessageAttributes);
@JsonProperty(MESSAGE_ID)
public String getMessageId();
@JsonProperty(MESSAGE_ID)
public void setMessageId(String messageId);
@JsonProperty(RECEIPT_HANDLE)
public String getReceiptHandle();
@JsonProperty(RECEIPT_HANDLE)
public void setReceiptHandle(String receiptHandle);
}
}
记录策略:
private static class UpperCaseRecordsPropertyNamingStrategy extends PropertyNamingStrategy.PropertyNamingStrategyBase {
private static final long serialVersionUID = 1L;
@Override
public String translate(String propertyName) {
if (propertyName.equals("records")) {
return "Records";
}
return propertyName;
}
}
日期格式化程序:
private static final DateTimeFormatter dateTimeFormatter = ISODateTimeFormat.dateTime()
.withZone(new FixedDateTimeZone("GMT", "GMT", 0, 0));
private static class DateTimeMapperModule extends SimpleModule {
private static final long serialVersionUID = 1L;
public DateTimeMapperModule() {
super("DateTimeMapperModule");
super.addSerializer(DateTime.class, new DateTimeSerializer());
super.addDeserializer(DateTime.class, new DateTimeDeserializer());
}
}
private static class DateTimeSerializer extends JsonSerializer<DateTime> {
@Override
public void serialize(DateTime value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeString(dateTimeFormatter.print(value));
}
}
private static class DateTimeDeserializer extends JsonDeserializer<DateTime> {
@Override
public DateTime deserialize(JsonParser parser, DeserializationContext context) throws IOException {
return dateTimeFormatter.parseDateTime(parser.getText());
}
}
并声明您的映射器:
ObjectMapper mapper = new ObjectMapper();
mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
mapper.setPropertyNamingStrategy(new UpperCaseRecordsPropertyNamingStrategy());
mapper.registerModule(new DateTimeMapperModule());
mapper.addMixIn(SQSMessage.class, SQSEventMixin.MessageMixin.class);
SQSEvent request = mapper.convertValue(inputObject, SQSEvent.class);
我用更简单的方式解决了这个问题。
引用 https://docs.aws.amazon.com/lambda/latest/dg/java-handler-io-type-stream.html 并具体
if Lambda's serialization approach does not meet your needs, you can use the byte stream implementation
我现在直接使用 SpringBootStreamHandler,并且在我的 Spring 配置 class 中创建了一个包含所需配置选项的 ObjectMapper 实例:
@Bean
public ObjectMapper objectMapper() {
final ObjectMapper mapper = new ObjectMapper();
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return mapper;
}
已经有一个官方库支持这个:https://aws.amazon.com/blogs/opensource/testing-aws-lambda-functions-written-in-java/
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-tests</artifactId>
<version>1.0.0</version>
<scope>test</scope>
</dependency>
你的插件中也有 surefire:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</plugin>
</plugins>
</build>
示例:
SQSEvent input = EventLoader.loadEvent("/sqsEvent.json", SQSEvent.class);