在 spring 数据 elasticsearch 中序列化 AggregatedPage 时出现 jackson 解析错误
Getting jackson parsing error while serializing AggregatedPage in spring data elasticsearch
我正在尝试使用 spring 数据 elasticsearch 在 elasticsearch 中创建一个用于聚合的休息 api 点。我能够在服务层获取数据但是当控制器(即@RestController)试图return它给邮递员时我收到这个错误。
Could not write JSON: For input string:
"bHRMZzc5aHdodDF5a0hOck15Lzl1UT09"; nested exception is
com.fasterxml.jackson.databind.JsonMappingException: For input string:
"bHRMZzc5aHdodDF5a0hOck15Lzl1UT09" (through reference chain:
org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl["aggregations"]->org.elasticsearch.search.aggregations.InternalAggregations["asMap"]->java.util.Collections$UnmodifiableMap["memberNumberToken"]->org.elasticsearch.search.aggregations.bucket.terms.StringTerms["buckets"]->java.util.ArrayList[0]->org.elasticsearch.search.aggregations.bucket.terms.StringTerms$Bucket["keyAsNumber"])
我的映射文件是这个
{
"transactions" : {
"properties" : {
"refernceId" : {
"type" :"text",
"index": true,
"store": true
},
"postingDate" : {
"type" : "date",
"index": true,
"store": true,
"format" : "yyyy-MM-dd'T'HH:mm:ss'Z'"
},
"effectiveDate" : {
"type" : "date",
"index": true,
"store": true,
"format" : "yyyy-MM-dd'T'HH:mm:ss'Z'"
},
"effectiveTime" : {
"type" : "text",
"index": true,
"store": true
},
"effectiveEpochTime" : {
"type" : "long",
"index": true,
"store": true
},
"transactionAmount" : {
"type" : "double",
"index": true,
"store": true
},
"transactionType" : {
"type" : "keyword",
"index": true,
"store": true
},
"transactionDesc" : {
"type" : "text",
"index": true,
"store": true
},
"transactionMemo" : {
"type" : "text",
"index": true,
"store": true
},
"transactionNumber" : {
"type" : "text",
"index": true,
"store": true
},
"transactionTypeCode" : {
"type" : "text",
"index": true,
"store": true
},
"transactionStatus" : {
"type" : "keyword",
"index": true,
"store": true
},
"principalAmount" : {
"type" : "double",
"index": true,
"store": true
},
"interest" : {
"type" : "text",
"index": true,
"store": true
},
"accountNumberToken" : {
"type" : "keyword",
"index": true,
"store": true
},
"memberNumberToken" : {
"type" : "keyword",
"index": true,
"store": true
},
"accountType" : {
"type" : "keyword",
"index": true,
"store": true
},
"userSub" : {
"type" : "keyword",
"index": true,
"store": true
},
"tenant" : {
"type" : "keyword",
"index": true,
"store": true
}
}
}
}
我的 pom 文件:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tyfone</groupId>
<artifactId>mcb-search-feature</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>mcb-search-feature Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<jdk.version>1.8</jdk.version>
<spring.version>5.0.1.RELEASE</spring.version>
<jstl.version>1.2</jstl.version>
<servletapi.version>4.0.0</servletapi.version>
<spring.data.elastic.version>3.0.2.RELEASE</spring.data.elastic.version>
<slf4j.version>1.7.25</slf4j.version>
<junit.version>3.8.1</junit.version>
</properties>
<dependencies>
<!-- Spring MVC framework -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- JSTL -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
<!-- for compile only, your container should have this -->
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servletapi.version}</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-elasticsearch -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>${spring.data.elastic.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-simple -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.25</version>
<scope>test</scope>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
<!-- Testing pojo classes -->
<dependency>
<groupId>com.googlecode.openpojo</groupId>
<artifactId>openpojo</artifactId>
<version>0.6.0</version>
<scope>test</scope>
</dependency>
<!-- <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId>
<version>${junit.version}</version> <exclusions> <exclusion> <groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId> </exclusion> </exclusions> </dependency> -->
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>mcb-search-feature</finalName>
</build>
</project>
如果还有人感兴趣。有完全相同的问题。这与 Jackson 并不真正知道 AggregatedPage 中包含的正确类型有关。因此,它简单地遍历所有 getter 并在 keyAsNumber 上绊倒,其中键不是数字,在您的情况下为 bHRMZzc5aHdodDF5a0hOck15Lzl1UT09。这最终导致异常。
我最终在 Spring 应用程序启动期间配置 Jackson 以在序列化期间省略 keyAsNumber。
所以这对我有用:
@Configuration
public class JacksonConfig {
@Bean
public Jackson2ObjectMapperBuilderCustomizer changeKeyAsNumber() {
return new Jackson2ObjectMapperBuilderCustomizer() {
@Override
public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
jacksonObjectMapperBuilder.mixIn(StringTerms.Bucket.class, MixIn.class);
}
};
}
}
abstract class MixIn {
@JsonIgnore
abstract public Number getKeyAsNumber();
}
我按照 Amaresh Kulkarni 的建议使用 ParsedStringTerms.ParsedBucket.class 而不是 StringTerms.Bucket.class 使其正常工作。这是完整的 JacksonConfiguraton
@Configuration
public class JacksonConfig {
@Bean
public Jackson2ObjectMapperBuilderCustomizer changeKeyAsNumber() {
return new Jackson2ObjectMapperBuilderCustomizer() {
@Override
public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
jacksonObjectMapperBuilder.mixIn(ParsedStringTerms.ParsedBucket.class, MixIn.class);
}
};
}
}
abstract class MixIn {
@JsonIgnore
abstract public Number getKeyAsNumber();
}
对于搜索后来到这里的任何人:
我 运行 遇到了同样的问题并使用了 WebFlux。看起来它需要一个额外的配置。我合并了 sung sung 的代码和这里的答案:
我完成的代码如下所示:
@Configuration
public class JacksonConfig{
@Bean
public Jackson2ObjectMapperBuilderCustomizer changeKeyAsNumber() {
return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.mixIn(ParsedStringTerms.ParsedBucket.class, MixIn.class);
}
@Bean
JavaTimeModule javaTimeModule(){
return new JavaTimeModule();
}
@Bean
public Jackson2JsonEncoder jackson2JsonEncoder(ObjectMapper objectMapper){
return new Jackson2JsonEncoder(objectMapper);
}
@Bean
public Jackson2JsonDecoder jackson2JsonDecoder(ObjectMapper objectMapper){
return new Jackson2JsonDecoder(objectMapper);
}
@Bean
public WebFluxConfigurer webFluxConfigurer(Jackson2JsonEncoder encoder, Jackson2JsonDecoder decoder){
return new WebFluxConfigurer() {
@Override
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
configurer.defaultCodecs().jackson2JsonEncoder(encoder);
configurer.defaultCodecs().jackson2JsonDecoder(decoder);
}
};
}
}
abstract class MixIn {
@JsonIgnore
abstract public Number getKeyAsNumber();
}
我正在尝试使用 spring 数据 elasticsearch 在 elasticsearch 中创建一个用于聚合的休息 api 点。我能够在服务层获取数据但是当控制器(即@RestController)试图return它给邮递员时我收到这个错误。
Could not write JSON: For input string: "bHRMZzc5aHdodDF5a0hOck15Lzl1UT09"; nested exception is com.fasterxml.jackson.databind.JsonMappingException: For input string: "bHRMZzc5aHdodDF5a0hOck15Lzl1UT09" (through reference chain: org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl["aggregations"]->org.elasticsearch.search.aggregations.InternalAggregations["asMap"]->java.util.Collections$UnmodifiableMap["memberNumberToken"]->org.elasticsearch.search.aggregations.bucket.terms.StringTerms["buckets"]->java.util.ArrayList[0]->org.elasticsearch.search.aggregations.bucket.terms.StringTerms$Bucket["keyAsNumber"])
我的映射文件是这个
{
"transactions" : {
"properties" : {
"refernceId" : {
"type" :"text",
"index": true,
"store": true
},
"postingDate" : {
"type" : "date",
"index": true,
"store": true,
"format" : "yyyy-MM-dd'T'HH:mm:ss'Z'"
},
"effectiveDate" : {
"type" : "date",
"index": true,
"store": true,
"format" : "yyyy-MM-dd'T'HH:mm:ss'Z'"
},
"effectiveTime" : {
"type" : "text",
"index": true,
"store": true
},
"effectiveEpochTime" : {
"type" : "long",
"index": true,
"store": true
},
"transactionAmount" : {
"type" : "double",
"index": true,
"store": true
},
"transactionType" : {
"type" : "keyword",
"index": true,
"store": true
},
"transactionDesc" : {
"type" : "text",
"index": true,
"store": true
},
"transactionMemo" : {
"type" : "text",
"index": true,
"store": true
},
"transactionNumber" : {
"type" : "text",
"index": true,
"store": true
},
"transactionTypeCode" : {
"type" : "text",
"index": true,
"store": true
},
"transactionStatus" : {
"type" : "keyword",
"index": true,
"store": true
},
"principalAmount" : {
"type" : "double",
"index": true,
"store": true
},
"interest" : {
"type" : "text",
"index": true,
"store": true
},
"accountNumberToken" : {
"type" : "keyword",
"index": true,
"store": true
},
"memberNumberToken" : {
"type" : "keyword",
"index": true,
"store": true
},
"accountType" : {
"type" : "keyword",
"index": true,
"store": true
},
"userSub" : {
"type" : "keyword",
"index": true,
"store": true
},
"tenant" : {
"type" : "keyword",
"index": true,
"store": true
}
}
}
}
我的 pom 文件:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.tyfone</groupId>
<artifactId>mcb-search-feature</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>mcb-search-feature Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<jdk.version>1.8</jdk.version>
<spring.version>5.0.1.RELEASE</spring.version>
<jstl.version>1.2</jstl.version>
<servletapi.version>4.0.0</servletapi.version>
<spring.data.elastic.version>3.0.2.RELEASE</spring.data.elastic.version>
<slf4j.version>1.7.25</slf4j.version>
<junit.version>3.8.1</junit.version>
</properties>
<dependencies>
<!-- Spring MVC framework -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- JSTL -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
<!-- for compile only, your container should have this -->
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servletapi.version}</version>
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-elasticsearch -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>${spring.data.elastic.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-simple -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.25</version>
<scope>test</scope>
</dependency>
<!-- Test -->
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
<!-- Testing pojo classes -->
<dependency>
<groupId>com.googlecode.openpojo</groupId>
<artifactId>openpojo</artifactId>
<version>0.6.0</version>
<scope>test</scope>
</dependency>
<!-- <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId>
<version>${junit.version}</version> <exclusions> <exclusion> <groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId> </exclusion> </exclusions> </dependency> -->
<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>mcb-search-feature</finalName>
</build>
</project>
如果还有人感兴趣。有完全相同的问题。这与 Jackson 并不真正知道 AggregatedPage 中包含的正确类型有关。因此,它简单地遍历所有 getter 并在 keyAsNumber 上绊倒,其中键不是数字,在您的情况下为 bHRMZzc5aHdodDF5a0hOck15Lzl1UT09。这最终导致异常。
我最终在 Spring 应用程序启动期间配置 Jackson 以在序列化期间省略 keyAsNumber。
所以这对我有用:
@Configuration
public class JacksonConfig {
@Bean
public Jackson2ObjectMapperBuilderCustomizer changeKeyAsNumber() {
return new Jackson2ObjectMapperBuilderCustomizer() {
@Override
public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
jacksonObjectMapperBuilder.mixIn(StringTerms.Bucket.class, MixIn.class);
}
};
}
}
abstract class MixIn {
@JsonIgnore
abstract public Number getKeyAsNumber();
}
我按照 Amaresh Kulkarni 的建议使用 ParsedStringTerms.ParsedBucket.class 而不是 StringTerms.Bucket.class 使其正常工作。这是完整的 JacksonConfiguraton
@Configuration
public class JacksonConfig {
@Bean
public Jackson2ObjectMapperBuilderCustomizer changeKeyAsNumber() {
return new Jackson2ObjectMapperBuilderCustomizer() {
@Override
public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
jacksonObjectMapperBuilder.mixIn(ParsedStringTerms.ParsedBucket.class, MixIn.class);
}
};
}
}
abstract class MixIn {
@JsonIgnore
abstract public Number getKeyAsNumber();
}
对于搜索后来到这里的任何人:
我 运行 遇到了同样的问题并使用了 WebFlux。看起来它需要一个额外的配置。我合并了 sung sung 的代码和这里的答案:
我完成的代码如下所示:
@Configuration
public class JacksonConfig{
@Bean
public Jackson2ObjectMapperBuilderCustomizer changeKeyAsNumber() {
return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.mixIn(ParsedStringTerms.ParsedBucket.class, MixIn.class);
}
@Bean
JavaTimeModule javaTimeModule(){
return new JavaTimeModule();
}
@Bean
public Jackson2JsonEncoder jackson2JsonEncoder(ObjectMapper objectMapper){
return new Jackson2JsonEncoder(objectMapper);
}
@Bean
public Jackson2JsonDecoder jackson2JsonDecoder(ObjectMapper objectMapper){
return new Jackson2JsonDecoder(objectMapper);
}
@Bean
public WebFluxConfigurer webFluxConfigurer(Jackson2JsonEncoder encoder, Jackson2JsonDecoder decoder){
return new WebFluxConfigurer() {
@Override
public void configureHttpMessageCodecs(ServerCodecConfigurer configurer) {
configurer.defaultCodecs().jackson2JsonEncoder(encoder);
configurer.defaultCodecs().jackson2JsonDecoder(decoder);
}
};
}
}
abstract class MixIn {
@JsonIgnore
abstract public Number getKeyAsNumber();
}