Skip to content

Commit 1e08067

Browse files
committed
Merge remote-tracking branch 'origin/2.13' into github_464_pr3
2 parents f5433e8 + daf5bdc commit 1e08067

File tree

7 files changed

+127
-12
lines changed

7 files changed

+127
-12
lines changed

.circleci/config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ orbs:
33
maven: circleci/[email protected]
44
workflows:
55
maven_test:
6+
when: false
67
jobs:
78
- maven/test

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,30 @@ myMemberWithType = mapper.readValue(json)
100100
All inferred types for the extension functions carry in full generic information (reified generics).
101101
Therefore, using `readValue()` extension without the `Class` parameter will reify the type and automatically create a `TypeReference` for Jackson.
102102

103+
Also, there are some convenient operator overloading extension functions for JsonNode inheritors.
104+
```kotlin
105+
import com.fasterxml.jackson.databind.node.ArrayNode
106+
import com.fasterxml.jackson.databind.node.ObjectNode
107+
import com.fasterxml.jackson.databind.node.JsonNodeFactory
108+
import com.fasterxml.jackson.module.kotlin.*
109+
110+
// ...
111+
val objectNode: ObjectNode = JsonNodeFactory.instance.objectNode()
112+
objectNode.put("foo1", "bar").put("foo2", "baz").put("foo3", "bax")
113+
objectNode -= "foo1"
114+
objectNode -= listOf("foo2")
115+
println(objectNode.toString()) // {"foo3":"bax"}
116+
117+
// ...
118+
val arrayNode: ArrayNode = JsonNodeFactory.instance.arrayNode()
119+
arrayNode += "foo"
120+
arrayNode += true
121+
arrayNode += 1
122+
arrayNode += 1.0
123+
arrayNode += "bar".toByteArray()
124+
println(arrayNode.toString()) // ["foo",true,1,1.0,"YmFy"]
125+
```
126+
103127
# Annotations
104128

105129
You can intermix non-field values in the constructor and `JsonProperty` annotation in the constructor.
@@ -124,6 +148,7 @@ Note that using `lateinit` or `Delegates.notNull()` will ensure that the value i
124148
* If using proguard:
125149
* `kotlin.Metadata` annotations may be stripped, preventing deserialization. Add a proguard rule to keep the `kotlin.Metadata` class: `-keep class kotlin.Metadata { *; }`
126150
* If you're getting `java.lang.ExceptionInInitializerError`, you may also need: `-keep class kotlin.reflect.** { *; }`
151+
* 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.** { *; }`
127152

128153
# Support for Kotlin Built-in classes
129154

pom.xml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
<parent>
99
<groupId>com.fasterxml.jackson</groupId>
1010
<artifactId>jackson-base</artifactId>
11-
<version>2.13.0-rc2-SNAPSHOT</version>
11+
<version>2.13.0-SNAPSHOT</version>
1212
</parent>
1313
<groupId>com.fasterxml.jackson.module</groupId>
1414
<artifactId>jackson-module-kotlin</artifactId>
1515
<name>jackson-module-kotlin</name>
16-
<version>2.13.0-rc2-SNAPSHOT</version>
16+
<version>2.13.0-SNAPSHOT</version>
1717
<packaging>bundle</packaging>
1818
<description>Add-on module for Jackson (https://github.com/FasterXML/jackson/) to support
1919
Kotlin language, specifically introspection of method/constructor parameter names,
@@ -52,7 +52,7 @@
5252
<javac.src.version>1.8</javac.src.version>
5353
<javac.target.version>1.8</javac.target.version>
5454

55-
<version.kotlin>1.5.10</version.kotlin>
55+
<version.kotlin>1.5.30</version.kotlin>
5656

5757
<!-- Generate PackageVersion.java into this directory. -->
5858
<packageVersion.dir>com/fasterxml/jackson/module/kotlin</packageVersion.dir>
@@ -226,6 +226,7 @@
226226
TODO Remove after release of 2.13 and update the oldVersion above to 2.13.
227227
-->
228228
<exclude>com.fasterxml.jackson.module.kotlin.ValueClassUnboxSerializer</exclude>
229+
<exclude>com.fasterxml.jackson.module.kotlin.ExtensionsKt$treeToValue</exclude>
229230
</excludes>
230231
</parameter>
231232
</configuration>

release-notes/CREDITS-2.x

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@ Authors:
1313

1414
Contributors:
1515

16+
Fedor Bobin (Fuud@github)
17+
* #496, #45: Fix treeToValue extension function should not have type erasure
18+
(2.13)
19+
20+
Mikhael Sokolov (sokomishalov@github)
21+
* #489: JsonNode, ArrayNode and ObjectNode extension functions
22+
23+
Max Wiechmann (MaxMello@github)
24+
* #494: ProGuard ProTips in the README
25+
1626
Róbert Papp (TWiStErRob@github)
1727
* #477: KotlinFeature documentation & deprecation replacements
1828

release-notes/VERSION-2.x

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Co-maintainers:
1919
#438: Fixed mapping failure when `private` `companion object` is named
2020
(reported, fix contributed by k163377@github)
2121

22+
2.12.5 (27-Aug-2021)
2223
2.12.4 (06-Jul-2021)
2324
2.12.3 (12-Apr-2021)
2425

src/main/kotlin/com/fasterxml/jackson/module/kotlin/Extensions.kt

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,16 @@ package com.fasterxml.jackson.module.kotlin
33
import com.fasterxml.jackson.core.JsonParser
44
import com.fasterxml.jackson.core.TreeNode
55
import com.fasterxml.jackson.core.type.TypeReference
6-
import com.fasterxml.jackson.databind.JsonMappingException
7-
import com.fasterxml.jackson.databind.MappingIterator
8-
import com.fasterxml.jackson.databind.ObjectMapper
9-
import com.fasterxml.jackson.databind.ObjectReader
10-
import com.fasterxml.jackson.databind.module.SimpleModule
11-
import com.fasterxml.jackson.databind.JsonDeserializer
12-
import com.fasterxml.jackson.databind.JsonSerializer
6+
import com.fasterxml.jackson.databind.*
137
import com.fasterxml.jackson.databind.json.JsonMapper
8+
import com.fasterxml.jackson.databind.module.SimpleModule
9+
import com.fasterxml.jackson.databind.node.ArrayNode
10+
import com.fasterxml.jackson.databind.node.ObjectNode
1411
import java.io.File
1512
import java.io.InputStream
1613
import java.io.Reader
14+
import java.math.BigDecimal
15+
import java.math.BigInteger
1716
import java.net.URL
1817
import java.util.*
1918
import kotlin.reflect.KClass
@@ -47,12 +46,47 @@ inline fun <reified T> ObjectMapper.readValue(src: Reader): T = readValue(src, j
4746
inline fun <reified T> ObjectMapper.readValue(src: InputStream): T = readValue(src, jacksonTypeRef<T>())
4847
inline fun <reified T> ObjectMapper.readValue(src: ByteArray): T = readValue(src, jacksonTypeRef<T>())
4948

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

5352
inline fun <reified T> ObjectReader.readValueTyped(jp: JsonParser): T = readValue(jp, jacksonTypeRef<T>())
5453
inline fun <reified T> ObjectReader.readValuesTyped(jp: JsonParser): Iterator<T> = readValues(jp, jacksonTypeRef<T>())
55-
inline fun <reified T> ObjectReader.treeToValue(n: TreeNode): T? = treeToValue(n, T::class.java)
54+
inline fun <reified T> ObjectReader.treeToValue(n: TreeNode): T? = readValue(this.treeAsTokens(n), jacksonTypeRef<T>())
55+
56+
operator fun ArrayNode.plus(element: Boolean) = Unit.apply { add(element) }
57+
operator fun ArrayNode.plus(element: Short) = Unit.apply { add(element) }
58+
operator fun ArrayNode.plus(element: Int) = Unit.apply { add(element) }
59+
operator fun ArrayNode.plus(element: Long) = Unit.apply { add(element) }
60+
operator fun ArrayNode.plus(element: Float) = Unit.apply { add(element) }
61+
operator fun ArrayNode.plus(element: Double) = Unit.apply { add(element) }
62+
operator fun ArrayNode.plus(element: BigDecimal) = Unit.apply { add(element) }
63+
operator fun ArrayNode.plus(element: BigInteger) = Unit.apply { add(element) }
64+
operator fun ArrayNode.plus(element: String) = Unit.apply { add(element) }
65+
operator fun ArrayNode.plus(element: ByteArray) = Unit.apply { add(element) }
66+
operator fun ArrayNode.plus(element: JsonNode) = Unit.apply { add(element) }
67+
operator fun ArrayNode.plus(elements: ArrayNode) = Unit.apply { addAll(elements) }
68+
operator fun ArrayNode.plusAssign(element: Boolean) = Unit.apply { add(element) }
69+
operator fun ArrayNode.plusAssign(element: Short) = Unit.apply { add(element) }
70+
operator fun ArrayNode.plusAssign(element: Int) = Unit.apply { add(element) }
71+
operator fun ArrayNode.plusAssign(element: Long) = Unit.apply { add(element) }
72+
operator fun ArrayNode.plusAssign(element: Float) = Unit.apply { add(element) }
73+
operator fun ArrayNode.plusAssign(element: Double) = Unit.apply { add(element) }
74+
operator fun ArrayNode.plusAssign(element: BigDecimal) = Unit.apply { add(element) }
75+
operator fun ArrayNode.plusAssign(element: BigInteger) = Unit.apply { add(element) }
76+
operator fun ArrayNode.plusAssign(element: String) = Unit.apply { add(element) }
77+
operator fun ArrayNode.plusAssign(element: ByteArray) = Unit.apply { add(element) }
78+
operator fun ArrayNode.plusAssign(element: JsonNode) = Unit.apply { add(element) }
79+
operator fun ArrayNode.plusAssign(elements: ArrayNode) = Unit.apply { addAll(elements) }
80+
operator fun ArrayNode.minus(index: Int) = Unit.apply { remove(index) }
81+
operator fun ArrayNode.minusAssign(index: Int) = Unit.apply { remove(index) }
82+
83+
operator fun ObjectNode.minus(field: String) = Unit.apply { remove(field) }
84+
operator fun ObjectNode.minus(fields: Collection<String>) = Unit.apply { remove(fields) }
85+
operator fun ObjectNode.minusAssign(field: String) = Unit.apply { remove(field) }
86+
operator fun ObjectNode.minusAssign(fields: Collection<String>) = Unit.apply { remove(fields) }
87+
88+
operator fun JsonNode.contains(field: String) = has(field)
89+
operator fun JsonNode.contains(index: Int) = has(index)
5690

5791
internal fun JsonMappingException.wrapWithPath(refFrom: Any?, refFieldName: String) = JsonMappingException.wrapWithPath(this, refFrom, refFieldName)
5892
internal fun JsonMappingException.wrapWithPath(refFrom: Any?, index: Int) = JsonMappingException.wrapWithPath(this, refFrom, index)

src/test/kotlin/com/fasterxml/jackson/module/kotlin/test/ExtensionMethodsTests.kt

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package com.fasterxml.jackson.module.kotlin.test
22

33
import com.fasterxml.jackson.databind.ObjectMapper
44
import com.fasterxml.jackson.databind.SerializationFeature
5+
import com.fasterxml.jackson.databind.node.JsonNodeFactory
56
import com.fasterxml.jackson.module.kotlin.*
7+
import org.hamcrest.CoreMatchers.`is`
68
import org.hamcrest.CoreMatchers.equalTo
79
import org.hamcrest.MatcherAssert.assertThat
810
import org.junit.Test
@@ -33,4 +35,45 @@ class TestExtensionMethods {
3335
val myList: List<MyData> = mapper.readValue(jsonStr)
3436
assertThat(myList, equalTo(listOf(MyData("value1", 1), MyData("value2", 2))))
3537
}
38+
39+
@Test fun testOperatorFunExtensions() {
40+
val factory = JsonNodeFactory.instance
41+
42+
val objectNode = factory.objectNode()
43+
objectNode.put("foo1", "bar")
44+
objectNode.put("foo2", "baz")
45+
objectNode.put("foo3", "bah")
46+
objectNode -= "foo1"
47+
objectNode -= listOf("foo2")
48+
49+
assertThat("foo1" !in objectNode, `is`(true))
50+
assertThat("foo3" in objectNode, `is`(true))
51+
52+
val arrayNode = factory.arrayNode()
53+
arrayNode += "foo"
54+
arrayNode += true
55+
arrayNode += 1
56+
arrayNode += 1.0
57+
arrayNode += "bar".toByteArray()
58+
59+
assertThat(arrayNode.size(), `is`(5))
60+
61+
(4 downTo 0).forEach { arrayNode -= it }
62+
assertThat(arrayNode.size(), `is`(0))
63+
}
64+
65+
@Test fun noTypeErasure(){
66+
data class Person(val name: String)
67+
val source = """[ { "name" : "Neo" } ]"""
68+
val tree = mapper.readTree(source)
69+
70+
val readValueResult: List<Person> = mapper.readValue(source)
71+
assertThat(readValueResult, `is`(listOf(Person("Neo"))))
72+
73+
val treeToValueResult: List<Person> = mapper.treeToValue(tree)
74+
assertThat(treeToValueResult, `is`(listOf(Person("Neo"))))
75+
76+
val convertValueResult: List<Person> = mapper.convertValue(tree)
77+
assertThat(convertValueResult, `is`(listOf(Person("Neo"))))
78+
}
3679
}

0 commit comments

Comments
 (0)