@@ -9,6 +9,7 @@ import com.fasterxml.jackson.databind.JsonSerializer
99import com.fasterxml.jackson.databind.MappingIterator
1010import com.fasterxml.jackson.databind.ObjectMapper
1111import com.fasterxml.jackson.databind.ObjectReader
12+ import com.fasterxml.jackson.databind.RuntimeJsonMappingException
1213import com.fasterxml.jackson.databind.json.JsonMapper
1314import com.fasterxml.jackson.databind.module.SimpleModule
1415import com.fasterxml.jackson.databind.node.ArrayNode
@@ -52,28 +53,138 @@ public fun ObjectMapper.registerKotlinModule(
5253
5354public inline fun <reified T > jacksonTypeRef (): TypeReference <T > = object : TypeReference <T >() {}
5455
56+ /* *
57+ * It is public due to Kotlin restrictions, but should not be used externally.
58+ */
59+ public inline fun <reified T > Any?.checkTypeMismatch (): T {
60+ // Basically, this check assumes that T is non-null and the value is null.
61+ // Since this can be caused by both input or ObjectMapper implementation errors,
62+ // a more abstract RuntimeJsonMappingException is thrown.
63+ if (this !is T ) {
64+ val nullability = if (null is T ) " ?" else " (non-null)"
65+
66+ // Since the databind implementation of MappingIterator throws RuntimeJsonMappingException,
67+ // JsonMappingException was not used to unify the behavior.
68+ throw RuntimeJsonMappingException (
69+ " Deserialized value did not match the specified type; " +
70+ " specified ${T ::class .qualifiedName}$nullability but was ${this ?.let { it::class .qualifiedName }} "
71+ )
72+ }
73+ return this
74+ }
75+
76+ /* *
77+ * Shorthand for [ObjectMapper.readValue].
78+ * @throws RuntimeJsonMappingException Especially if [T] is non-null and the value read is null.
79+ * Other cases where the read value is of a different type than [T]
80+ * due to an incorrect customization to [ObjectMapper].
81+ */
5582public inline fun <reified T > ObjectMapper.readValue (jp : JsonParser ): T = readValue(jp, jacksonTypeRef<T >())
83+ .checkTypeMismatch()
84+
85+ // TODO: After importing 2.19, import the changes in kotlin-module and uncomment the tests.
5686public inline fun <reified T > ObjectMapper.readValues (
5787 jp : JsonParser
5888): MappingIterator <T > = readValues(jp, jacksonTypeRef<T >())
5989
90+ /* *
91+ * Shorthand for [ObjectMapper.readValue].
92+ * @throws RuntimeJsonMappingException Especially if [T] is non-null and the value read is null.
93+ * Other cases where the read value is of a different type than [T]
94+ * due to an incorrect customization to [ObjectMapper].
95+ */
6096public inline fun <reified T > ObjectMapper.readValue (src : File ): T = readValue(src, jacksonTypeRef<T >())
97+ .checkTypeMismatch()
98+
99+ /* *
100+ * Shorthand for [ObjectMapper.readValue].
101+ * @throws RuntimeJsonMappingException Especially if [T] is non-null and the value read is null.
102+ * Other cases where the read value is of a different type than [T]
103+ * due to an incorrect customization to [ObjectMapper].
104+ */
61105public inline fun <reified T > ObjectMapper.readValue (src : URL ): T = readValue(src, jacksonTypeRef<T >())
106+ .checkTypeMismatch()
107+
108+ /* *
109+ * Shorthand for [ObjectMapper.readValue].
110+ * @throws RuntimeJsonMappingException Especially if [T] is non-null and the value read is null.
111+ * Other cases where the read value is of a different type than [T]
112+ * due to an incorrect customization to [ObjectMapper].
113+ */
62114public inline fun <reified T > ObjectMapper.readValue (content : String ): T = readValue(content, jacksonTypeRef<T >())
115+ .checkTypeMismatch()
116+
117+ /* *
118+ * Shorthand for [ObjectMapper.readValue].
119+ * @throws RuntimeJsonMappingException Especially if [T] is non-null and the value read is null.
120+ * Other cases where the read value is of a different type than [T]
121+ * due to an incorrect customization to [ObjectMapper].
122+ */
63123public inline fun <reified T > ObjectMapper.readValue (src : Reader ): T = readValue(src, jacksonTypeRef<T >())
124+ .checkTypeMismatch()
125+
126+ /* *
127+ * Shorthand for [ObjectMapper.readValue].
128+ * @throws RuntimeJsonMappingException Especially if [T] is non-null and the value read is null.
129+ * Other cases where the read value is of a different type than [T]
130+ * due to an incorrect customization to [ObjectMapper].
131+ */
64132public inline fun <reified T > ObjectMapper.readValue (src : InputStream ): T = readValue(src, jacksonTypeRef<T >())
133+ .checkTypeMismatch()
134+
135+ /* *
136+ * Shorthand for [ObjectMapper.readValue].
137+ * @throws RuntimeJsonMappingException Especially if [T] is non-null and the value read is null.
138+ * Other cases where the read value is of a different type than [T]
139+ * due to an incorrect customization to [ObjectMapper].
140+ */
65141public inline fun <reified T > ObjectMapper.readValue (src : ByteArray ): T = readValue(src, jacksonTypeRef<T >())
142+ .checkTypeMismatch()
143+
144+ /* *
145+ * Shorthand for [ObjectMapper.readValue].
146+ * @throws RuntimeJsonMappingException Especially if [T] is non-null and the value read is null.
147+ * Other cases where the read value is of a different type than [T]
148+ * due to an incorrect customization to [ObjectMapper].
149+ */
150+ public inline fun <reified T > ObjectMapper.treeToValue (
151+ n : TreeNode
152+ ): T = readValue(this .treeAsTokens(n), jacksonTypeRef<T >()).checkTypeMismatch()
66153
67- public inline fun <reified T > ObjectMapper.treeToValue (n : TreeNode ): T = readValue(treeAsTokens(n), jacksonTypeRef<T >())
154+ /* *
155+ * Shorthand for [ObjectMapper.convertValue].
156+ * @throws RuntimeJsonMappingException Especially if [T] is non-null and the value read is null.
157+ * Other cases where the read value is of a different type than [T]
158+ * due to an incorrect customization to [ObjectMapper].
159+ */
68160public inline fun <reified T > ObjectMapper.convertValue (from : Any? ): T = convertValue(from, jacksonTypeRef<T >())
161+ .checkTypeMismatch()
69162
163+ /* *
164+ * Shorthand for [ObjectReader.readValue].
165+ * @throws RuntimeJsonMappingException Especially if [T] is non-null and the value read is null.
166+ * Other cases where the read value is of a different type than [T]
167+ * due to an incorrect customization to [ObjectReader].
168+ */
70169public inline fun <reified T > ObjectReader.readValueTyped (jp : JsonParser ): T = readValue(jp, jacksonTypeRef<T >())
71- public inline fun <reified T > ObjectReader.readValuesTyped (
72- jp : JsonParser
73- ): Iterator <T > = readValues(jp, jacksonTypeRef<T >())
170+ .checkTypeMismatch()
171+
172+ /* *
173+ * Shorthand for [ObjectReader.readValues].
174+ * @throws RuntimeJsonMappingException Especially if [T] is non-null and the value read is null.
175+ * Other cases where the read value is of a different type than [T]
176+ * due to an incorrect customization to [ObjectReader].
177+ */
178+ public inline fun <reified T > ObjectReader.readValuesTyped (jp : JsonParser ): Iterator <T > {
179+ val values = readValues(jp, jacksonTypeRef<T >())
180+
181+ return object : Iterator <T > by values {
182+ override fun next (): T = values.next().checkTypeMismatch<T >()
183+ }
184+ }
74185public inline fun <reified T > ObjectReader.treeToValue (
75186 n : TreeNode
76- ): T ? = readValue(treeAsTokens(n), jacksonTypeRef<T >())
187+ ): T ? = readValue(this . treeAsTokens(n), jacksonTypeRef<T >())
77188
78189public inline fun <reified T , reified U > ObjectMapper.addMixIn (): ObjectMapper = addMixIn(T ::class .java, U ::class .java)
79190public inline fun <reified T , reified U > JsonMapper.Builder.addMixIn (): JsonMapper .Builder = addMixIn(
0 commit comments