Skip to content

Commit 23a30a7

Browse files
committed
Merge branch '2.8'
2 parents c59ad69 + 64967c4 commit 23a30a7

File tree

6 files changed

+65
-9
lines changed

6 files changed

+65
-9
lines changed

release-notes/CREDITS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,10 @@ Josh Caplan (jecaplan@github)
496496
of non-ignored `processor` property (added in 2.7)
497497
(2.7.8)
498498

499+
Diego de Estrada (diegode@github)
500+
* Contributed fix for #1367: No Object Id found for an instance when using `@ConstructorProperties`
501+
(2.7.9)
502+
499503
Kevin Hogeland (khogeland@github)
500504
* Reported #1501: `ArrayIndexOutOfBoundsException` on non-static inner class constructor
501505
(2.7.9)

release-notes/VERSION

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,12 @@ Project: jackson-databind
5757

5858
#935: `@JsonProperty(access = Access.READ_ONLY)` - unexpected behaviour
5959
#1317: '@JsonIgnore' annotation not working with creator properties, serialization
60+
#1367: No Object Id found for an instance when using `@ConstructorProperties`
6061
#1505: @JsonEnumDefaultValue should take precedence over FAIL_ON_NUMBERS_FOR_ENUMS
6162
(suggested by Stephan S)
63+
#1506: Missing `KeyDeserializer` for `CharSequence`
64+
#1513: `MapSerializer._orderEntries()` throws NPE when operating on `ConcurrentHashMap`
65+
(reported by Sovietaced@github)
6266
- Simplified processing of class annotations (for `AnnotatedClass`) to try to
6367
solve rare concurrency problems with "root name" annotations.
6468

@@ -197,6 +201,8 @@ Project: jackson-databind
197201

198202
2.7.9 (not released yet)
199203

204+
#1367: No Object Id found for an instance when using `@ConstructorProperties`
205+
(reported by kajo-bellabeat@github; fix by diegode@github)
200206
#1432: Off by 1 bug in PropertyValueBuffer
201207
(reported by Kevin D)
202208
#1439: NPE when using with filter id, serializing `java.util.Map` types

src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,10 @@ protected Object _deserializeUsingPropertyBased(final JsonParser p, final Deseri
389389
for (; t == JsonToken.FIELD_NAME; t = p.nextToken()) {
390390
String propName = p.getCurrentName();
391391
p.nextToken(); // to point to value
392+
// Object Id property?
393+
if (buffer.readIdProperty(propName)) {
394+
continue;
395+
}
392396
// creator property?
393397
SettableBeanProperty creatorProp = creator.findCreatorProperty(propName);
394398
if (creatorProp != null) {
@@ -426,10 +430,6 @@ protected Object _deserializeUsingPropertyBased(final JsonParser p, final Deseri
426430
}
427431
continue;
428432
}
429-
// Object Id property?
430-
if (buffer.readIdProperty(propName)) {
431-
continue;
432-
}
433433
// regular property? needs buffering
434434
SettableBeanProperty prop = _beanProperties.find(propName);
435435
if (prop != null) {

src/main/java/com/fasterxml/jackson/databind/ser/std/MapSerializer.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,8 +1004,11 @@ protected Map<?,?> _orderEntries(Map<?,?> input, JsonGenerator gen,
10041004
if (input instanceof SortedMap<?,?>) {
10051005
return input;
10061006
}
1007-
// [databind#1411]: TreeMap does not like null key...
1008-
if (input.containsKey(null)) {
1007+
// [databind#1411]: TreeMap does not like null key... (although note that
1008+
// check above should prevent this code from being called in that case)
1009+
// [databind#153]: but, apparently, some custom Maps do manage hit this
1010+
// problem.
1011+
if (_hasNullKey(input)) {
10091012
TreeMap<Object,Object> result = new TreeMap<Object,Object>();
10101013
for (Map.Entry<?,?> entry : input.entrySet()) {
10111014
Object key = entry.getKey();
@@ -1020,6 +1023,22 @@ protected Map<?,?> _orderEntries(Map<?,?> input, JsonGenerator gen,
10201023
return new TreeMap<Object,Object>(input);
10211024
}
10221025

1026+
/**
1027+
* @since 2.8.7
1028+
*/
1029+
protected boolean _hasNullKey(Map<?,?> input) {
1030+
// 19-Feb-2017, tatu: As per [databind#1513] there are many cases where `null`
1031+
// keys are not allowed, and even attempt to check for presence can cause
1032+
// problems. Without resorting to external sorting (and internal API change),
1033+
// or custom sortable Map implementation (more code) we can try black- or
1034+
// white-listing (that is; either skip known problem cases; or only apply for
1035+
// known good cases).
1036+
// While my first instinct was to do black-listing (remove Hashtable and ConcurrentHashMap),
1037+
// all in all it is probably better to just white list `HashMap` (and its sub-classes).
1038+
1039+
return (input instanceof HashMap) && input.containsKey(null);
1040+
}
1041+
10231042
protected void _writeNullKeyedEntry(JsonGenerator gen, SerializerProvider provider,
10241043
Object value) throws IOException
10251044
{

src/test/java/com/fasterxml/jackson/failing/ObjectIdWithCreator1367Test.java renamed to src/test/java/com/fasterxml/jackson/databind/creators/CreatorWithObjectIdTest.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
package com.fasterxml.jackson.failing;
1+
package com.fasterxml.jackson.databind.creators;
22

33
import java.beans.ConstructorProperties;
44

55
import com.fasterxml.jackson.annotation.JsonIdentityInfo;
66
import com.fasterxml.jackson.annotation.ObjectIdGenerators;
77
import com.fasterxml.jackson.databind.*;
88

9-
public class ObjectIdWithCreator1367Test
9+
// for [databind#1367]
10+
public class CreatorWithObjectIdTest
1011
extends BaseMapTest
1112
{
1213
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
@@ -37,7 +38,7 @@ public void setName(String name) {
3738
}
3839
}
3940

40-
public void testObjectIdWithCreator1367() throws Exception
41+
public void testObjectIdWithCreator() throws Exception
4142
{
4243
A a = new A("123", "A");
4344

src/test/java/com/fasterxml/jackson/databind/ser/TestMapSerialization.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.io.*;
44
import java.util.*;
55
import java.util.concurrent.ConcurrentHashMap;
6+
import java.util.concurrent.ConcurrentSkipListMap;
67

78
import com.fasterxml.jackson.annotation.*;
89
import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
@@ -284,4 +285,29 @@ public void testNullJsonInTypedMap691() throws Exception {
284285
String json = mapper.writeValueAsString(map);
285286
assertEquals("{\"@class\":\"java.util.HashMap\",\"NULL\":null}", json);
286287
}
288+
289+
// [databind#1513]
290+
public void testConcurrentMaps() throws Exception
291+
{
292+
final ObjectWriter w = MAPPER.writer(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS);
293+
294+
Map<String,String> input = new ConcurrentSkipListMap<String,String>();
295+
input.put("x", "y");
296+
input.put("a", "b");
297+
String json = w.writeValueAsString(input);
298+
assertEquals(aposToQuotes("{'a':'b','x':'y'}"), json);
299+
300+
input = new ConcurrentHashMap<String,String>();
301+
input.put("x", "y");
302+
input.put("a", "b");
303+
json = w.writeValueAsString(input);
304+
assertEquals(aposToQuotes("{'a':'b','x':'y'}"), json);
305+
306+
// One more: while not technically concurrent map at all, exhibits same issue
307+
input = new Hashtable<String,String>();
308+
input.put("x", "y");
309+
input.put("a", "b");
310+
json = w.writeValueAsString(input);
311+
assertEquals(aposToQuotes("{'a':'b','x':'y'}"), json);
312+
}
287313
}

0 commit comments

Comments
 (0)