Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/2.13' into github_464_pr3
Browse files Browse the repository at this point in the history
  • Loading branch information
dinomite committed Sep 28, 2021
2 parents f5433e8 + daf5bdc commit 1e08067
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 12 deletions.
1 change: 1 addition & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ orbs:
maven: circleci/maven@1.0.2
workflows:
maven_test:
when: false
jobs:
- maven/test
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,30 @@ myMemberWithType = mapper.readValue(json)
All inferred types for the extension functions carry in full generic information (reified generics).
Therefore, using `readValue()` extension without the `Class` parameter will reify the type and automatically create a `TypeReference` for Jackson.

Also, there are some convenient operator overloading extension functions for JsonNode inheritors.
```kotlin
import com.fasterxml.jackson.databind.node.ArrayNode
import com.fasterxml.jackson.databind.node.ObjectNode
import com.fasterxml.jackson.databind.node.JsonNodeFactory
import com.fasterxml.jackson.module.kotlin.*

// ...
val objectNode: ObjectNode = JsonNodeFactory.instance.objectNode()
objectNode.put("foo1", "bar").put("foo2", "baz").put("foo3", "bax")
objectNode -= "foo1"
objectNode -= listOf("foo2")
println(objectNode.toString()) // {"foo3":"bax"}

// ...
val arrayNode: ArrayNode = JsonNodeFactory.instance.arrayNode()
arrayNode += "foo"
arrayNode += true
arrayNode += 1
arrayNode += 1.0
arrayNode += "bar".toByteArray()
println(arrayNode.toString()) // ["foo",true,1,1.0,"YmFy"]
```

# Annotations

You can intermix non-field values in the constructor and `JsonProperty` annotation in the constructor.
Expand All @@ -124,6 +148,7 @@ Note that using `lateinit` or `Delegates.notNull()` will ensure that the value i
* If using proguard:
* `kotlin.Metadata` annotations may be stripped, preventing deserialization. Add a proguard rule to keep the `kotlin.Metadata` class: `-keep class kotlin.Metadata { *; }`
* If you're getting `java.lang.ExceptionInInitializerError`, you may also need: `-keep class kotlin.reflect.** { *; }`
* If you're still running into problems, you might also need to add a proguard keep rule for the specific classes you want to (de-)serialize. For example, if all your models are inside the package `com.example.models`, you could add the rule `-keep class com.example.models.** { *; }`

# Support for Kotlin Built-in classes

Expand Down
7 changes: 4 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
<parent>
<groupId>com.fasterxml.jackson</groupId>
<artifactId>jackson-base</artifactId>
<version>2.13.0-rc2-SNAPSHOT</version>
<version>2.13.0-SNAPSHOT</version>
</parent>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-kotlin</artifactId>
<name>jackson-module-kotlin</name>
<version>2.13.0-rc2-SNAPSHOT</version>
<version>2.13.0-SNAPSHOT</version>
<packaging>bundle</packaging>
<description>Add-on module for Jackson (https://github.com/FasterXML/jackson/) to support
Kotlin language, specifically introspection of method/constructor parameter names,
Expand Down Expand Up @@ -52,7 +52,7 @@
<javac.src.version>1.8</javac.src.version>
<javac.target.version>1.8</javac.target.version>

<version.kotlin>1.5.10</version.kotlin>
<version.kotlin>1.5.30</version.kotlin>

<!-- Generate PackageVersion.java into this directory. -->
<packageVersion.dir>com/fasterxml/jackson/module/kotlin</packageVersion.dir>
Expand Down Expand Up @@ -226,6 +226,7 @@
TODO Remove after release of 2.13 and update the oldVersion above to 2.13.
-->
<exclude>com.fasterxml.jackson.module.kotlin.ValueClassUnboxSerializer</exclude>
<exclude>com.fasterxml.jackson.module.kotlin.ExtensionsKt$treeToValue</exclude>
</excludes>
</parameter>
</configuration>
Expand Down
10 changes: 10 additions & 0 deletions release-notes/CREDITS-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ Authors:

Contributors:

Fedor Bobin (Fuud@github)
* #496, #45: Fix treeToValue extension function should not have type erasure
(2.13)

Mikhael Sokolov (sokomishalov@github)
* #489: JsonNode, ArrayNode and ObjectNode extension functions

Max Wiechmann (MaxMello@github)
* #494: ProGuard ProTips in the README

Róbert Papp (TWiStErRob@github)
* #477: KotlinFeature documentation & deprecation replacements

Expand Down
1 change: 1 addition & 0 deletions release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ Co-maintainers:
#438: Fixed mapping failure when `private` `companion object` is named
(reported, fix contributed by k163377@github)

2.12.5 (27-Aug-2021)
2.12.4 (06-Jul-2021)
2.12.3 (12-Apr-2021)

Expand Down
52 changes: 43 additions & 9 deletions src/main/kotlin/com/fasterxml/jackson/module/kotlin/Extensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,16 @@ package com.fasterxml.jackson.module.kotlin
import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.core.TreeNode
import com.fasterxml.jackson.core.type.TypeReference
import com.fasterxml.jackson.databind.JsonMappingException
import com.fasterxml.jackson.databind.MappingIterator
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.ObjectReader
import com.fasterxml.jackson.databind.module.SimpleModule
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.JsonSerializer
import com.fasterxml.jackson.databind.*
import com.fasterxml.jackson.databind.json.JsonMapper
import com.fasterxml.jackson.databind.module.SimpleModule
import com.fasterxml.jackson.databind.node.ArrayNode
import com.fasterxml.jackson.databind.node.ObjectNode
import java.io.File
import java.io.InputStream
import java.io.Reader
import java.math.BigDecimal
import java.math.BigInteger
import java.net.URL
import java.util.*
import kotlin.reflect.KClass
Expand Down Expand Up @@ -47,12 +46,47 @@ inline fun <reified T> ObjectMapper.readValue(src: Reader): T = readValue(src, j
inline fun <reified T> ObjectMapper.readValue(src: InputStream): T = readValue(src, jacksonTypeRef<T>())
inline fun <reified T> ObjectMapper.readValue(src: ByteArray): T = readValue(src, jacksonTypeRef<T>())

inline fun <reified T> ObjectMapper.treeToValue(n: TreeNode): T? = treeToValue(n, T::class.java)
inline fun <reified T> ObjectMapper.treeToValue(n: TreeNode): T = readValue(this.treeAsTokens(n), jacksonTypeRef<T>())
inline fun <reified T> ObjectMapper.convertValue(from: Any): T = convertValue(from, jacksonTypeRef<T>())

inline fun <reified T> ObjectReader.readValueTyped(jp: JsonParser): T = readValue(jp, jacksonTypeRef<T>())
inline fun <reified T> ObjectReader.readValuesTyped(jp: JsonParser): Iterator<T> = readValues(jp, jacksonTypeRef<T>())
inline fun <reified T> ObjectReader.treeToValue(n: TreeNode): T? = treeToValue(n, T::class.java)
inline fun <reified T> ObjectReader.treeToValue(n: TreeNode): T? = readValue(this.treeAsTokens(n), jacksonTypeRef<T>())

operator fun ArrayNode.plus(element: Boolean) = Unit.apply { add(element) }
operator fun ArrayNode.plus(element: Short) = Unit.apply { add(element) }
operator fun ArrayNode.plus(element: Int) = Unit.apply { add(element) }
operator fun ArrayNode.plus(element: Long) = Unit.apply { add(element) }
operator fun ArrayNode.plus(element: Float) = Unit.apply { add(element) }
operator fun ArrayNode.plus(element: Double) = Unit.apply { add(element) }
operator fun ArrayNode.plus(element: BigDecimal) = Unit.apply { add(element) }
operator fun ArrayNode.plus(element: BigInteger) = Unit.apply { add(element) }
operator fun ArrayNode.plus(element: String) = Unit.apply { add(element) }
operator fun ArrayNode.plus(element: ByteArray) = Unit.apply { add(element) }
operator fun ArrayNode.plus(element: JsonNode) = Unit.apply { add(element) }
operator fun ArrayNode.plus(elements: ArrayNode) = Unit.apply { addAll(elements) }
operator fun ArrayNode.plusAssign(element: Boolean) = Unit.apply { add(element) }
operator fun ArrayNode.plusAssign(element: Short) = Unit.apply { add(element) }
operator fun ArrayNode.plusAssign(element: Int) = Unit.apply { add(element) }
operator fun ArrayNode.plusAssign(element: Long) = Unit.apply { add(element) }
operator fun ArrayNode.plusAssign(element: Float) = Unit.apply { add(element) }
operator fun ArrayNode.plusAssign(element: Double) = Unit.apply { add(element) }
operator fun ArrayNode.plusAssign(element: BigDecimal) = Unit.apply { add(element) }
operator fun ArrayNode.plusAssign(element: BigInteger) = Unit.apply { add(element) }
operator fun ArrayNode.plusAssign(element: String) = Unit.apply { add(element) }
operator fun ArrayNode.plusAssign(element: ByteArray) = Unit.apply { add(element) }
operator fun ArrayNode.plusAssign(element: JsonNode) = Unit.apply { add(element) }
operator fun ArrayNode.plusAssign(elements: ArrayNode) = Unit.apply { addAll(elements) }
operator fun ArrayNode.minus(index: Int) = Unit.apply { remove(index) }
operator fun ArrayNode.minusAssign(index: Int) = Unit.apply { remove(index) }

operator fun ObjectNode.minus(field: String) = Unit.apply { remove(field) }
operator fun ObjectNode.minus(fields: Collection<String>) = Unit.apply { remove(fields) }
operator fun ObjectNode.minusAssign(field: String) = Unit.apply { remove(field) }
operator fun ObjectNode.minusAssign(fields: Collection<String>) = Unit.apply { remove(fields) }

operator fun JsonNode.contains(field: String) = has(field)
operator fun JsonNode.contains(index: Int) = has(index)

internal fun JsonMappingException.wrapWithPath(refFrom: Any?, refFieldName: String) = JsonMappingException.wrapWithPath(this, refFrom, refFieldName)
internal fun JsonMappingException.wrapWithPath(refFrom: Any?, index: Int) = JsonMappingException.wrapWithPath(this, refFrom, index)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package com.fasterxml.jackson.module.kotlin.test

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.databind.node.JsonNodeFactory
import com.fasterxml.jackson.module.kotlin.*
import org.hamcrest.CoreMatchers.`is`
import org.hamcrest.CoreMatchers.equalTo
import org.hamcrest.MatcherAssert.assertThat
import org.junit.Test
Expand Down Expand Up @@ -33,4 +35,45 @@ class TestExtensionMethods {
val myList: List<MyData> = mapper.readValue(jsonStr)
assertThat(myList, equalTo(listOf(MyData("value1", 1), MyData("value2", 2))))
}

@Test fun testOperatorFunExtensions() {
val factory = JsonNodeFactory.instance

val objectNode = factory.objectNode()
objectNode.put("foo1", "bar")
objectNode.put("foo2", "baz")
objectNode.put("foo3", "bah")
objectNode -= "foo1"
objectNode -= listOf("foo2")

assertThat("foo1" !in objectNode, `is`(true))
assertThat("foo3" in objectNode, `is`(true))

val arrayNode = factory.arrayNode()
arrayNode += "foo"
arrayNode += true
arrayNode += 1
arrayNode += 1.0
arrayNode += "bar".toByteArray()

assertThat(arrayNode.size(), `is`(5))

(4 downTo 0).forEach { arrayNode -= it }
assertThat(arrayNode.size(), `is`(0))
}

@Test fun noTypeErasure(){
data class Person(val name: String)
val source = """[ { "name" : "Neo" } ]"""
val tree = mapper.readTree(source)

val readValueResult: List<Person> = mapper.readValue(source)
assertThat(readValueResult, `is`(listOf(Person("Neo"))))

val treeToValueResult: List<Person> = mapper.treeToValue(tree)
assertThat(treeToValueResult, `is`(listOf(Person("Neo"))))

val convertValueResult: List<Person> = mapper.convertValue(tree)
assertThat(convertValueResult, `is`(listOf(Person("Neo"))))
}
}

0 comments on commit 1e08067

Please sign in to comment.