diff --git a/build.sbt b/build.sbt index 22cd2bb2a7..601d9eac8e 100644 --- a/build.sbt +++ b/build.sbt @@ -176,9 +176,9 @@ lazy val clientesjava = (project in file("elastic4s-client-esjava")) libraryDependencies ++= Seq( elasticsearchRestClient, log4jApi, - "com.fasterxml.jackson.core" % "jackson-core" % JacksonVersion, - "com.fasterxml.jackson.core" % "jackson-databind" % JacksonVersion, - "com.fasterxml.jackson.module" %% "jackson-module-scala" % JacksonVersion exclude ( + fasterXmlJacksonCore, + fasterXmlJacksonDatabind, + fasterXmlJacksonModuleScala exclude ( "org.scala-lang", "scala-library" ) @@ -262,11 +262,13 @@ lazy val jackson = (project in file("elastic4s-json-jackson")) .settings(name := "elastic4s-json-jackson") .settings(scala3Settings) .settings( - libraryDependencies += "com.fasterxml.jackson.core" % "jackson-core" % JacksonVersion, - libraryDependencies += "com.fasterxml.jackson.core" % "jackson-databind" % JacksonVersion, - libraryDependencies += "com.fasterxml.jackson.module" %% "jackson-module-scala" % JacksonVersion exclude ( - "org.scala-lang", - "scala-library" + libraryDependencies ++= Seq( + fasterXmlJacksonCore, + fasterXmlJacksonDatabind, + fasterXmlJacksonModuleScala exclude ( + "org.scala-lang", + "scala-library" + ) ) ) @@ -341,15 +343,15 @@ lazy val tests = (project in file("elastic4s-tests")) libraryDependencies ++= Seq( commonsIo, mockitoCore, - "com.fasterxml.jackson.core" % "jackson-core" % JacksonVersion % Test, - "com.fasterxml.jackson.core" % "jackson-databind" % JacksonVersion % Test, - "com.fasterxml.jackson.module" %% "jackson-module-scala" % JacksonVersion % Test exclude ( + fasterXmlJacksonCore % Test, + fasterXmlJacksonDatabind % Test, + fasterXmlJacksonModuleScala % Test exclude ( "org.scala-lang", "scala-library" ), - "org.apache.logging.log4j" % "log4j-api" % "2.25.2" % Test, - "org.apache.logging.log4j" % "log4j-slf4j-impl" % "2.25.2" % Test, - "org.apache.logging.log4j" % "log4j-core" % "2.25.2" % Test + "org.apache.logging.log4j" % "log4j-api" % "2.25.2" % Test, + "org.apache.logging.log4j" % "log4j-slf4j-impl" % "2.25.2" % Test, + "org.apache.logging.log4j" % "log4j-core" % "2.25.2" % Test ), Test / fork := false, Test / parallelExecution := false, diff --git a/elastic4s-core/src/main/scala/com/sksamuel/elastic4s/requests/searches/SearchHandlers.scala b/elastic4s-core/src/main/scala/com/sksamuel/elastic4s/requests/searches/SearchHandlers.scala index 9669c9ecad..a38ef2ba23 100644 --- a/elastic4s-core/src/main/scala/com/sksamuel/elastic4s/requests/searches/SearchHandlers.scala +++ b/elastic4s-core/src/main/scala/com/sksamuel/elastic4s/requests/searches/SearchHandlers.scala @@ -29,7 +29,7 @@ trait SearchHandlers { val json = JacksonSupport.mapper.readTree(response.entity.get.content) val items = Option(json.get("responses")) match { case Some(node) => - node.elements + node.values .asScala .zipWithIndex .map { diff --git a/elastic4s-core/src/test/scala/com/sksamuel/elastic4s/JsonSugar.scala b/elastic4s-core/src/test/scala/com/sksamuel/elastic4s/JsonSugar.scala index ab0619f015..a8ccff6a8c 100644 --- a/elastic4s-core/src/test/scala/com/sksamuel/elastic4s/JsonSugar.scala +++ b/elastic4s-core/src/test/scala/com/sksamuel/elastic4s/JsonSugar.scala @@ -1,14 +1,18 @@ package com.sksamuel.elastic4s -import com.fasterxml.jackson.databind.ObjectMapper -import com.fasterxml.jackson.module.scala.{ClassTagExtensions, DefaultScalaModule} +import com.fasterxml.jackson.annotation.JsonInclude +import tools.jackson.databind.{DeserializationFeature, ObjectMapper} +import tools.jackson.module.scala.{ClassTagExtensions, DefaultScalaModule} import org.scalatest.matchers.should.Matchers import org.scalatest.matchers.{MatchResult, Matcher} +import tools.jackson.core.json.{JsonFactory, JsonReadFeature} +import tools.jackson.databind.json.JsonMapper trait JsonSugar extends Matchers { - - private val mapper = new ObjectMapper with ClassTagExtensions - mapper.registerModule(DefaultScalaModule) + private val mapper: ObjectMapper with ClassTagExtensions = + JsonMapper.builder(JsonFactory.builder().build()) + .addModule(DefaultScalaModule) + .build() :: ClassTagExtensions def matchJsonResource(resourceName: String) = new JsonResourceMatcher(resourceName) @@ -38,7 +42,7 @@ trait JsonSugar extends Matchers { jsonResource should not be null } - val expectedJson = mapper.readTree(jsonResource) + val expectedJson = mapper.readTree(jsonResource.openStream()) val actualJson = mapper.readTree(left) MatchResult( diff --git a/elastic4s-domain/src/main/scala/com/sksamuel/elastic4s/requests/searches/aggs/responses/JacksonSupport.scala b/elastic4s-domain/src/main/scala/com/sksamuel/elastic4s/requests/searches/aggs/responses/JacksonSupport.scala index c3fdae6055..2a4ea316b2 100644 --- a/elastic4s-domain/src/main/scala/com/sksamuel/elastic4s/requests/searches/aggs/responses/JacksonSupport.scala +++ b/elastic4s-domain/src/main/scala/com/sksamuel/elastic4s/requests/searches/aggs/responses/JacksonSupport.scala @@ -1,19 +1,24 @@ package com.sksamuel.elastic4s.requests.searches.aggs.responses import com.fasterxml.jackson.annotation.JsonInclude -import com.fasterxml.jackson.core.JsonParser -import com.fasterxml.jackson.databind.{DeserializationFeature, ObjectMapper} -import com.fasterxml.jackson.module.scala.{ClassTagExtensions, DefaultScalaModule} +import tools.jackson.core.json.{JsonFactory, JsonReadFeature} +import tools.jackson.databind.json.JsonMapper +import tools.jackson.databind.{DeserializationFeature, ObjectMapper} +import tools.jackson.module.scala.{ClassTagExtensions, DefaultScalaModule} object JacksonSupport { - - val mapper: ObjectMapper with ClassTagExtensions = new ObjectMapper with ClassTagExtensions - mapper.registerModule(DefaultScalaModule) - - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL) - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - mapper.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false) - mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true) - mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true) - mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true) + val mapper: ObjectMapper with ClassTagExtensions = { + val jf = JsonFactory.builder() + .enable(JsonReadFeature.ALLOW_UNQUOTED_PROPERTY_NAMES) + .enable(JsonReadFeature.ALLOW_SINGLE_QUOTES) + .build() + JsonMapper.builder(jf) + .addModule(DefaultScalaModule) + .changeDefaultPropertyInclusion(_.withValueInclusion(JsonInclude.Include.NON_NULL)) + .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + .disable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES) + .enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY) + .disable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES) + .build() :: ClassTagExtensions + } } diff --git a/elastic4s-handlers/src/main/scala/com/sksamuel/elastic4s/Handler.scala b/elastic4s-handlers/src/main/scala/com/sksamuel/elastic4s/Handler.scala index eba28d8ecc..f8419684f8 100644 --- a/elastic4s-handlers/src/main/scala/com/sksamuel/elastic4s/Handler.scala +++ b/elastic4s-handlers/src/main/scala/com/sksamuel/elastic4s/Handler.scala @@ -1,6 +1,6 @@ package com.sksamuel.elastic4s -import com.fasterxml.jackson.module.scala.JavaTypeable +import tools.jackson.module.scala.JavaTypeable import org.slf4j.{Logger, LoggerFactory} /** A [[Handler]] is a typeclass used to create [[ElasticRequest]] instances from elastic4s models, which are the sent diff --git a/elastic4s-handlers/src/main/scala/com/sksamuel/elastic4s/ResponseHandler.scala b/elastic4s-handlers/src/main/scala/com/sksamuel/elastic4s/ResponseHandler.scala index cb3ac2d7d7..e83095c6c8 100644 --- a/elastic4s-handlers/src/main/scala/com/sksamuel/elastic4s/ResponseHandler.scala +++ b/elastic4s-handlers/src/main/scala/com/sksamuel/elastic4s/ResponseHandler.scala @@ -1,8 +1,8 @@ package com.sksamuel.elastic4s -import com.fasterxml.jackson.databind.JsonNode -import com.fasterxml.jackson.databind.`type`.TypeFactory -import com.fasterxml.jackson.module.scala.JavaTypeable +import tools.jackson.databind.JsonNode +import tools.jackson.databind.`type`.TypeFactory +import tools.jackson.module.scala.JavaTypeable import com.sksamuel.elastic4s.handlers.ElasticErrorParser import com.sksamuel.elastic4s.ext.OptionImplicits.RichOption import org.slf4j.{Logger, LoggerFactory} @@ -31,7 +31,7 @@ object ResponseHandler { def fromNode[U: JavaTypeable](node: JsonNode): U = { logger.debug( - s"Attempting to unmarshall json node to ${implicitly[JavaTypeable[U]].asJavaType(TypeFactory.defaultInstance).getRawClass.getName}" + s"Attempting to unmarshall json node to ${implicitly[JavaTypeable[U]].asJavaType(TypeFactory.createDefaultInstance()).getRawClass.getName}" ) JacksonSupport.mapper.readValue[U](JacksonSupport.mapper.writeValueAsBytes(node)) } @@ -41,7 +41,7 @@ object ResponseHandler { def fromEntity[U: JavaTypeable](entity: HttpEntity.StringEntity): U = { logger.debug( - s"Attempting to unmarshall response to ${implicitly[JavaTypeable[U]].asJavaType(TypeFactory.defaultInstance).getRawClass.getName}" + s"Attempting to unmarshall response to ${implicitly[JavaTypeable[U]].asJavaType(TypeFactory.createDefaultInstance()).getRawClass.getName}" ) logger.debug(entity.content) JacksonSupport.mapper.readValue[U](entity.content) diff --git a/elastic4s-handlers/src/main/scala/com/sksamuel/elastic4s/handlers/JacksonSupport.scala b/elastic4s-handlers/src/main/scala/com/sksamuel/elastic4s/handlers/JacksonSupport.scala index 5be06318ee..8b021af1cc 100644 --- a/elastic4s-handlers/src/main/scala/com/sksamuel/elastic4s/handlers/JacksonSupport.scala +++ b/elastic4s-handlers/src/main/scala/com/sksamuel/elastic4s/handlers/JacksonSupport.scala @@ -1,19 +1,24 @@ package com.sksamuel.elastic4s.handlers import com.fasterxml.jackson.annotation.JsonInclude -import com.fasterxml.jackson.core.JsonParser -import com.fasterxml.jackson.databind.{DeserializationFeature, ObjectMapper} -import com.fasterxml.jackson.module.scala.{ClassTagExtensions, DefaultScalaModule} +import tools.jackson.core.json.{JsonFactory, JsonReadFeature} +import tools.jackson.databind.json.JsonMapper +import tools.jackson.databind.{DeserializationFeature, ObjectMapper} +import tools.jackson.module.scala.{ClassTagExtensions, DefaultScalaModule} object JacksonSupport { - - val mapper: ObjectMapper with ClassTagExtensions = new ObjectMapper with ClassTagExtensions - mapper.registerModule(DefaultScalaModule) - - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL) - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - mapper.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false) - mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true) - mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true) - mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true) + val mapper: ObjectMapper with ClassTagExtensions = { + val jf = JsonFactory.builder() + .enable(JsonReadFeature.ALLOW_UNQUOTED_PROPERTY_NAMES) + .enable(JsonReadFeature.ALLOW_SINGLE_QUOTES) + .build() + JsonMapper.builder(jf) + .addModule(DefaultScalaModule) + .changeDefaultPropertyInclusion(_.withValueInclusion(JsonInclude.Include.NON_NULL)) + .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + .disable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES) + .enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY) + .disable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES) + .build() :: ClassTagExtensions + } } diff --git a/elastic4s-handlers/src/main/scala/com/sksamuel/elastic4s/handlers/alias/IndexAliasHandlers.scala b/elastic4s-handlers/src/main/scala/com/sksamuel/elastic4s/handlers/alias/IndexAliasHandlers.scala index 350824f1ae..339a80e90f 100644 --- a/elastic4s-handlers/src/main/scala/com/sksamuel/elastic4s/handlers/alias/IndexAliasHandlers.scala +++ b/elastic4s-handlers/src/main/scala/com/sksamuel/elastic4s/handlers/alias/IndexAliasHandlers.scala @@ -21,7 +21,7 @@ trait IndexAliasHandlers { case 200 => val root = ResponseHandler.json(response.entity.get) val map = root.properties.asScala.toVector.map { entry => - Index(entry.getKey) -> entry.getValue.get("aliases").fieldNames.asScala.toList.map(Alias.apply) + Index(entry.getKey) -> entry.getValue.get("aliases").propertyNames.asScala.toList.map(Alias.apply) }.toMap Right(IndexAliases(map)) case 404 => Right(IndexAliases(Map.empty)) diff --git a/elastic4s-handlers/src/main/scala/com/sksamuel/elastic4s/handlers/get/GetHandlers.scala b/elastic4s-handlers/src/main/scala/com/sksamuel/elastic4s/handlers/get/GetHandlers.scala index f0b3cbbeb4..ed4ae85a19 100644 --- a/elastic4s-handlers/src/main/scala/com/sksamuel/elastic4s/handlers/get/GetHandlers.scala +++ b/elastic4s-handlers/src/main/scala/com/sksamuel/elastic4s/handlers/get/GetHandlers.scala @@ -1,6 +1,6 @@ package com.sksamuel.elastic4s.handlers.get -import com.fasterxml.jackson.databind.JsonNode +import tools.jackson.databind.JsonNode import com.sksamuel.elastic4s.handlers.common.FetchSourceContextQueryParameterFn import com.sksamuel.elastic4s.handlers.{ElasticErrorParser, VersionTypeHttpString} import com.sksamuel.elastic4s.requests.get.{GetRequest, GetResponse, MultiGetRequest, MultiGetResponse} diff --git a/elastic4s-json-builder/src/main/scala/com/sksamuel/elastic4s/JacksonSupport.scala b/elastic4s-json-builder/src/main/scala/com/sksamuel/elastic4s/JacksonSupport.scala index 22f8d39522..9829f3a8f9 100644 --- a/elastic4s-json-builder/src/main/scala/com/sksamuel/elastic4s/JacksonSupport.scala +++ b/elastic4s-json-builder/src/main/scala/com/sksamuel/elastic4s/JacksonSupport.scala @@ -1,32 +1,24 @@ package com.sksamuel.elastic4s import com.fasterxml.jackson.annotation.JsonInclude -import com.fasterxml.jackson.core.JsonParser -import com.fasterxml.jackson.databind.{DeserializationFeature, ObjectMapper} -import com.fasterxml.jackson.module.scala.{ClassTagExtensions, DefaultScalaModule} +import tools.jackson.core.json.{JsonFactory, JsonReadFeature} +import tools.jackson.databind.json.JsonMapper +import tools.jackson.databind.{DeserializationFeature, ObjectMapper} +import tools.jackson.module.scala.{ClassTagExtensions, DefaultScalaModule} object JacksonSupport { - - val mapper: ObjectMapper with ClassTagExtensions = new ObjectMapper with ClassTagExtensions - mapper.registerModule(DefaultScalaModule) - - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL) - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - mapper.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false) - mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true) - mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true) - mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true) - -// class Deserializer(vc: Class[_]) extends StdDeserializer[Total](vc) { -// override def deserialize(p: JsonParser, ctxt: DeserializationContext): Total = { -// val node: JsonNode = p.getCodec.readTree(p) -// if (node.isNumber) Total(node.toString.toLong, "eq") -// else Total(node.findValue("value").asLong, node.findValue("relation").asText()) -// } -// } -// -// val module = new SimpleModule { -// addDeserializer(classOf[Total], new Total.Deserializer(classOf[Total])) -// } -// mapper.registerModule(module) + val mapper: ObjectMapper with ClassTagExtensions = { + val jf = JsonFactory.builder() + .enable(JsonReadFeature.ALLOW_UNQUOTED_PROPERTY_NAMES) + .enable(JsonReadFeature.ALLOW_SINGLE_QUOTES) + .build() + JsonMapper.builder(jf) + .addModule(DefaultScalaModule) + .changeDefaultPropertyInclusion(_.withValueInclusion(JsonInclude.Include.NON_NULL)) + .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + .disable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES) + .enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY) + .disable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES) + .build() :: ClassTagExtensions + } } diff --git a/elastic4s-json-builder/src/main/scala/com/sksamuel/elastic4s/json/JacksonBuilder.scala b/elastic4s-json-builder/src/main/scala/com/sksamuel/elastic4s/json/JacksonBuilder.scala index ba368a5349..1c4ff6e549 100644 --- a/elastic4s-json-builder/src/main/scala/com/sksamuel/elastic4s/json/JacksonBuilder.scala +++ b/elastic4s-json-builder/src/main/scala/com/sksamuel/elastic4s/json/JacksonBuilder.scala @@ -1,6 +1,6 @@ package com.sksamuel.elastic4s.json -import com.fasterxml.jackson.databind.node.{ +import tools.jackson.databind.node.{ BooleanNode, DoubleNode, FloatNode, @@ -8,9 +8,9 @@ import com.fasterxml.jackson.databind.node.{ JsonNodeFactory, LongNode, NullNode, - TextNode + StringNode } -import com.fasterxml.jackson.databind.{JsonNode, util} +import tools.jackson.databind.{JsonNode, util} import com.sksamuel.elastic4s.JacksonSupport trait JsonBuilder { @@ -46,7 +46,7 @@ object JacksonBuilder extends JsonBuilder { ) } Left(node) - case StringValue(value) => Left(TextNode.valueOf(value)) + case StringValue(value) => Left(StringNode.valueOf(value)) case LongValue(value) => Left(LongNode.valueOf(value)) case IntValue(value) => Left(IntNode.valueOf(value)) case FloatValue(value) => Left(FloatNode.valueOf(value)) @@ -54,7 +54,7 @@ object JacksonBuilder extends JsonBuilder { case BooleanValue(value) => Left(BooleanNode.valueOf(value)) case BigDecimalValue(value) => Left(JsonNodeFactory.instance.numberNode(value.underlying())) case BigIntValue(value) => Left(JsonNodeFactory.instance.numberNode(value.underlying())) - case RawValue(value) => Right(new com.fasterxml.jackson.databind.util.RawValue(value)) + case RawValue(value) => Right(new tools.jackson.databind.util.RawValue(value)) case NullValue => Left(NullNode.instance) } } diff --git a/elastic4s-json-jackson/src/main/scala/com/sksamuel/elastic4s/jackson/ElasticJackson.scala b/elastic4s-json-jackson/src/main/scala/com/sksamuel/elastic4s/jackson/ElasticJackson.scala index c5f15d1fa6..670c9fdf87 100644 --- a/elastic4s-json-jackson/src/main/scala/com/sksamuel/elastic4s/jackson/ElasticJackson.scala +++ b/elastic4s-json-jackson/src/main/scala/com/sksamuel/elastic4s/jackson/ElasticJackson.scala @@ -1,8 +1,8 @@ package com.sksamuel.elastic4s.jackson -import com.fasterxml.jackson.databind.ObjectMapper -import com.fasterxml.jackson.databind.node.ObjectNode -import com.fasterxml.jackson.module.scala.{ClassTagExtensions, JavaTypeable} +import tools.jackson.databind.ObjectMapper +import tools.jackson.databind.node.ObjectNode +import tools.jackson.module.scala.{ClassTagExtensions, JavaTypeable} import com.sksamuel.elastic4s._ import org.slf4j.{Logger, LoggerFactory} diff --git a/elastic4s-json-jackson/src/main/scala/com/sksamuel/elastic4s/jackson/JacksonSupport.scala b/elastic4s-json-jackson/src/main/scala/com/sksamuel/elastic4s/jackson/JacksonSupport.scala index 85ddccefc1..f5d732283e 100644 --- a/elastic4s-json-jackson/src/main/scala/com/sksamuel/elastic4s/jackson/JacksonSupport.scala +++ b/elastic4s-json-jackson/src/main/scala/com/sksamuel/elastic4s/jackson/JacksonSupport.scala @@ -1,23 +1,28 @@ package com.sksamuel.elastic4s.jackson import com.fasterxml.jackson.annotation.JsonInclude -import com.fasterxml.jackson.core.JsonParser -import com.fasterxml.jackson.databind.module.SimpleModule -import com.fasterxml.jackson.databind.ser.std.NumberSerializers -import com.fasterxml.jackson.databind.{DeserializationFeature, ObjectMapper} -import com.fasterxml.jackson.module.scala.{ClassTagExtensions, DefaultScalaModule} +import tools.jackson.core.json.{JsonFactory, JsonReadFeature} +import tools.jackson.databind.json.JsonMapper +import tools.jackson.databind.module.SimpleModule +import tools.jackson.databind.ser.jdk.NumberSerializers +import tools.jackson.databind.{DeserializationFeature, ObjectMapper} +import tools.jackson.module.scala.{ClassTagExtensions, DefaultScalaModule} object JacksonSupport { - - val mapper: ObjectMapper with ClassTagExtensions = new ObjectMapper with ClassTagExtensions - mapper.registerModule(DefaultScalaModule) - - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL) - mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - mapper.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false) - mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true) - mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true) - mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true) + val mapper: ObjectMapper with ClassTagExtensions = { + val jf = JsonFactory.builder() + .enable(JsonReadFeature.ALLOW_UNQUOTED_PROPERTY_NAMES) + .enable(JsonReadFeature.ALLOW_SINGLE_QUOTES) + .build() + JsonMapper.builder(jf) + .addModule(DefaultScalaModule) + .changeDefaultPropertyInclusion(_.withValueInclusion(JsonInclude.Include.NON_NULL)) + .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + .disable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES) + .enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY) + .disable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES) + .build() :: ClassTagExtensions + } val module = new SimpleModule { addSerializer(new NumberSerializers.DoubleSerializer(classOf[Double])) diff --git a/elastic4s-tests/src/test/scala/com/sksamuel/elastic4s/JsonSugar.scala b/elastic4s-tests/src/test/scala/com/sksamuel/elastic4s/JsonSugar.scala index 520b1095ed..84e2f76e62 100644 --- a/elastic4s-tests/src/test/scala/com/sksamuel/elastic4s/JsonSugar.scala +++ b/elastic4s-tests/src/test/scala/com/sksamuel/elastic4s/JsonSugar.scala @@ -1,14 +1,18 @@ package com.sksamuel.elastic4s -import com.fasterxml.jackson.databind.ObjectMapper -import com.fasterxml.jackson.module.scala.{ClassTagExtensions, DefaultScalaModule} +import com.fasterxml.jackson.annotation.JsonInclude +import tools.jackson.databind.{DeserializationFeature, ObjectMapper} +import tools.jackson.module.scala.{ClassTagExtensions, DefaultScalaModule} import org.scalatest.matchers.should.Matchers import org.scalatest.matchers.{MatchResult, Matcher} +import tools.jackson.core.json.{JsonFactory, JsonReadFeature} +import tools.jackson.databind.json.JsonMapper trait JsonSugar extends Matchers { - - private val mapper = new ObjectMapper with ClassTagExtensions - mapper.registerModule(DefaultScalaModule) + private val mapper: ObjectMapper with ClassTagExtensions = + JsonMapper.builder(JsonFactory.builder().build()) + .addModule(DefaultScalaModule) + .build() :: ClassTagExtensions def matchJsonResource(resourceName: String) = new JsonResourceMatcher(resourceName) @@ -38,7 +42,7 @@ trait JsonSugar extends Matchers { jsonResource should not be null } - val expectedJson = mapper.readTree(jsonResource) + val expectedJson = mapper.readTree(jsonResource.openStream()) val actualJson = mapper.readTree(left) MatchResult( diff --git a/elastic4s-tests/src/test/scala/com/sksamuel/elastic4s/jackson/ElasticJacksonIndexableTest.scala b/elastic4s-tests/src/test/scala/com/sksamuel/elastic4s/jackson/ElasticJacksonIndexableTest.scala index ffdd14c9fb..b0f0b50541 100644 --- a/elastic4s-tests/src/test/scala/com/sksamuel/elastic4s/jackson/ElasticJacksonIndexableTest.scala +++ b/elastic4s-tests/src/test/scala/com/sksamuel/elastic4s/jackson/ElasticJacksonIndexableTest.scala @@ -1,16 +1,18 @@ package com.sksamuel.elastic4s.jackson -import com.fasterxml.jackson.core.JsonParser -import com.fasterxml.jackson.databind.module.SimpleModule -import com.fasterxml.jackson.databind.{DeserializationContext, JsonDeserializer, JsonMappingException, ObjectMapper} -import com.fasterxml.jackson.module.scala.ClassTagExtensions +import tools.jackson.core.JsonParser +import tools.jackson.databind.module.SimpleModule +import tools.jackson.databind.{DatabindException, DeserializationContext, ObjectMapper, ValueDeserializer} +import tools.jackson.module.scala.{ClassTagExtensions, DefaultScalaModule} import com.sksamuel.elastic4s.requests.common.RefreshPolicy import com.sksamuel.elastic4s.testkit.DockerTests import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec - import scala.util.Success +import tools.jackson.core.json.JsonFactory +import tools.jackson.databind.json.JsonMapper + class ElasticJacksonIndexableTest extends AnyWordSpec with Matchers with DockerTests { import ElasticJackson.Implicits._ @@ -45,24 +47,24 @@ class ElasticJacksonIndexableTest extends AnyWordSpec with Matchers with DockerT List(Success(CharacterWithIdAndIndex("2", "jacksontest", "hank", "breaking bad"))) } "support custom mapper" in { - - implicit val custom: ObjectMapper with ClassTagExtensions = new ObjectMapper with ClassTagExtensions - val module = new SimpleModule module.addDeserializer( classOf[String], - new JsonDeserializer[String] { - override def deserialize(p: JsonParser, ctxt: DeserializationContext): String = sys.error("boom") - } + (p: JsonParser, ctxt: DeserializationContext) => sys.error("boom") ) - custom.registerModule(module) + + implicit val custom: ObjectMapper with ClassTagExtensions = + JsonMapper.builder(JsonFactory.builder().build()) + .addModule(DefaultScalaModule) + .addModule(module) + .build() :: ClassTagExtensions val resp = client.execute { search("jacksontest").query("breaking") }.await.result // if our custom mapper has been picked up, then it should throw an exception when deserializing - intercept[JsonMappingException] { + intercept[DatabindException] { resp.to[Character].toList } } diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 12c3d36a4b..1e223700c5 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -11,7 +11,7 @@ object Dependencies { val ElasticsearchVersion = "9.2.0" val ExtsVersion = "1.61.1" val Http4sVersion = "0.23.33" - val JacksonVersion = "2.20.1" + val JacksonVersion = "3.0.1" val Json4sVersion = "4.1.0" val Log4jVersion = "2.25.2" val MockitoVersion = "5.20.0" @@ -42,11 +42,11 @@ object Dependencies { ) ) - lazy val fasterXmlJacksonScala = Seq( - "com.fasterxml.jackson.core" % "jackson-core" % JacksonVersion, - "com.fasterxml.jackson.core" % "jackson-databind" % JacksonVersion, - "com.fasterxml.jackson.module" %% "jackson-module-scala" % JacksonVersion - ) + lazy val fasterXmlJacksonCore = "tools.jackson.core" % "jackson-core" % JacksonVersion + lazy val fasterXmlJacksonDatabind = "tools.jackson.core" % "jackson-databind" % JacksonVersion + lazy val fasterXmlJacksonModuleScala = "tools.jackson.module" %% "jackson-module-scala" % JacksonVersion + + lazy val fasterXmlJacksonScala = Seq(fasterXmlJacksonCore, fasterXmlJacksonDatabind, fasterXmlJacksonModuleScala) lazy val zio1 = "dev.zio" %% "zio" % ZIO1Version lazy val zio = "dev.zio" %% "zio" % ZIOVersion