Skip to content

Commit 7003462

Browse files
committed
Implemented #463
1 parent c3b3704 commit 7003462

16 files changed

+123
-136
lines changed

release-notes/CREDITS

+5-2
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,10 @@ Ben Fagin: (UnquietCode@github)
126126
* Suggested #442: Make `@JsonUnwrapped` indicate property inclusion
127127
(2.4.0)
128128
* Contributed #81/#455: Allow use of @JsonUnwrapped with typed (@JsonTypeInfo) classes,
129-
provided that (new) feature `SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS`
130-
is disabled
129+
provided that (new) feature `SerializationFeature.FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS`
130+
is disabled
131131
(2.4.0)
132132

133+
Chris Cleveland:
134+
* Suggested #463: Add 'JsonNode.asText(String defaultValue)`
135+
(2.4.0)

release-notes/VERSION

+2
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ Version: 2.4.0-rc1 (26-Apr-2014)
4747
#447: ArrayNode#addAll should accept Collection<? extends JsonNode>
4848
(suggested by alias@github)
4949
#461: Add new standard naming strategy, `PropertyNamingStrategy.LowerCaseStrategy`
50+
#463: Add 'JsonNode.asText(String defaultValue)`
51+
(suggested by Chris C)
5052
- Slightly improve `SqlDateSerializer` to support `@JsonFormat`
5153
- Improve handling of native type ids (YAML, CBOR) to use non-native type ids
5254
as fallback

src/main/java/com/fasterxml/jackson/databind/JsonNode.java

+14-1
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,19 @@ public byte[] binaryValue() throws IOException {
509509
*/
510510
public abstract String asText();
511511

512+
/**
513+
* Method similar to {@link #asText()}, except that it will return
514+
* <code>defaultValue</code> in cases where null value would be returned;
515+
* either for missing nodes (trying to access missing property, or element
516+
* at invalid item for array) or explicit nulls.
517+
*
518+
* @since 2.4
519+
*/
520+
public String asText(String defaultValue) {
521+
String str = asText();
522+
return (str == null) ? defaultValue : str;
523+
}
524+
512525
/**
513526
* Method that will try to convert value of this node to a Java <b>int</b>.
514527
* Numbers are coerced using default Java rules; booleans convert to 0 (false)
@@ -522,7 +535,7 @@ public byte[] binaryValue() throws IOException {
522535
public int asInt() {
523536
return asInt(0);
524537
}
525-
538+
526539
/**
527540
* Method that will try to convert value of this node to a Java <b>int</b>.
528541
* Numbers are coerced using default Java rules; booleans convert to 0 (false)

src/main/java/com/fasterxml/jackson/databind/introspect/BeanPropertyDefinition.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -117,18 +117,18 @@ public boolean isExplicitlyNamed() {
117117

118118
public boolean couldDeserialize() { return getMutator() != null; }
119119
public boolean couldSerialize() { return getAccessor() != null; }
120-
120+
121121
/*
122122
/**********************************************************
123123
/* Access to accessors (fields, methods etc)
124124
/**********************************************************
125125
*/
126-
126+
127127
public abstract boolean hasGetter();
128128
public abstract boolean hasSetter();
129129
public abstract boolean hasField();
130130
public abstract boolean hasConstructorParameter();
131-
131+
132132
public abstract AnnotatedMethod getGetter();
133133
public abstract AnnotatedMethod getSetter();
134134
public abstract AnnotatedField getField();

src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public class POJOPropertiesCollector
9494
/* Life-cycle
9595
/**********************************************************
9696
*/
97-
97+
9898
protected POJOPropertiesCollector(MapperConfig<?> config, boolean forSerialization,
9999
JavaType type, AnnotatedClass classDef, String mutatorPrefix)
100100
{

src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertyBuilder.java

+6-1
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ public boolean isExplicitlyNamed() {
187187
/* BeanPropertyDefinition implementation, accessor access
188188
/**********************************************************
189189
*/
190-
190+
191191
@Override
192192
public boolean hasGetter() { return _getters != null; }
193193

@@ -200,6 +200,11 @@ public boolean isExplicitlyNamed() {
200200
@Override
201201
public boolean hasConstructorParameter() { return _ctorParameters != null; }
202202

203+
@Override
204+
public boolean couldDeserialize() {
205+
return (_ctorParameters != null) || (_setters != null) || (_fields != null);
206+
}
207+
203208
@Override
204209
public boolean couldSerialize() {
205210
return (_getters != null) || (_fields != null);

src/main/java/com/fasterxml/jackson/databind/node/MissingNode.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,10 @@ public JsonNodeType getNodeType()
4141

4242
@Override public JsonToken asToken() { return JsonToken.NOT_AVAILABLE; }
4343

44-
@Override
45-
public String asText() { return ""; }
44+
@Override public String asText() { return ""; }
4645

46+
@Override public String asText(String defaultValue) { return defaultValue; }
47+
4748
// // Note: not a numeric node, hence default 'asXxx()' are fine:
4849

4950
/*

src/main/java/com/fasterxml/jackson/databind/node/NullNode.java

+2-4
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,8 @@ public JsonNodeType getNodeType()
2929

3030
@Override public JsonToken asToken() { return JsonToken.VALUE_NULL; }
3131

32-
@Override
33-
public String asText() {
34-
return "null";
35-
}
32+
@Override public String asText(String defaultValue) { return defaultValue; }
33+
@Override public String asText() { return "null"; }
3634

3735
// as with MissingNode, not considered number node; hence defaults are returned if provided
3836

src/main/java/com/fasterxml/jackson/databind/node/POJONode.java

+5-3
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,12 @@ public byte[] binaryValue() throws IOException
5353
*/
5454

5555
@Override
56-
public String asText() {
57-
return (_value == null) ? "null" : _value.toString();
58-
}
56+
public String asText() { return (_value == null) ? "null" : _value.toString(); }
5957

58+
@Override public String asText(String defaultValue) {
59+
return (_value == null) ? defaultValue : _value.toString();
60+
}
61+
6062
@Override
6163
public boolean asBoolean(boolean defaultValue)
6264
{

src/main/java/com/fasterxml/jackson/databind/node/ValueNode.java

+13-42
Original file line numberDiff line numberDiff line change
@@ -61,52 +61,28 @@ public void serializeWithType(JsonGenerator jg, SerializerProvider provider,
6161
*/
6262

6363
@Override
64-
public final JsonNode get(int index)
65-
{
66-
return null;
67-
}
64+
public final JsonNode get(int index) { return null; }
6865

6966
@Override
70-
public final JsonNode path(int index)
71-
{
72-
return MissingNode.getInstance();
73-
}
67+
public final JsonNode path(int index) { return MissingNode.getInstance(); }
7468

7569
@Override
76-
public final boolean has(int index)
77-
{
78-
return false;
79-
}
70+
public final boolean has(int index) { return false; }
8071

8172
@Override
82-
public final boolean hasNonNull(int index)
83-
{
84-
return false;
85-
}
73+
public final boolean hasNonNull(int index) { return false; }
8674

8775
@Override
88-
public final JsonNode get(String fieldName)
89-
{
90-
return null;
91-
}
76+
public final JsonNode get(String fieldName) { return null; }
9277

9378
@Override
94-
public final JsonNode path(String fieldName)
95-
{
96-
return MissingNode.getInstance();
97-
}
79+
public final JsonNode path(String fieldName) { return MissingNode.getInstance(); }
9880

9981
@Override
100-
public final boolean has(String fieldName)
101-
{
102-
return false;
103-
}
82+
public final boolean has(String fieldName) { return false; }
10483

10584
@Override
106-
public final boolean hasNonNull(String fieldName)
107-
{
108-
return false;
109-
}
85+
public final boolean hasNonNull(String fieldName) { return false; }
11086

11187
/*
11288
**********************************************************************
@@ -115,33 +91,28 @@ public final boolean hasNonNull(String fieldName)
11591
*/
11692

11793
@Override
118-
public final JsonNode findValue(String fieldName)
119-
{
94+
public final JsonNode findValue(String fieldName) {
12095
return null;
12196
}
12297

12398
// note: co-variant return type
12499
@Override
125-
public final ObjectNode findParent(String fieldName)
126-
{
100+
public final ObjectNode findParent(String fieldName) {
127101
return null;
128102
}
129103

130104
@Override
131-
public final List<JsonNode> findValues(String fieldName, List<JsonNode> foundSoFar)
132-
{
105+
public final List<JsonNode> findValues(String fieldName, List<JsonNode> foundSoFar) {
133106
return foundSoFar;
134107
}
135108

136109
@Override
137-
public final List<String> findValuesAsText(String fieldName, List<String> foundSoFar)
138-
{
110+
public final List<String> findValuesAsText(String fieldName, List<String> foundSoFar) {
139111
return foundSoFar;
140112
}
141113

142114
@Override
143-
public final List<JsonNode> findParents(String fieldName, List<JsonNode> foundSoFar)
144-
{
115+
public final List<JsonNode> findParents(String fieldName, List<JsonNode> foundSoFar) {
145116
return foundSoFar;
146117
}
147118
}

src/test/java/com/fasterxml/jackson/databind/node/TestJsonNode.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ public void testText()
2626
assertEquals(value, n.asLong());
2727

2828
// and then with non-numeric input
29-
assertNodeNumbersForNonNumeric(TextNode.valueOf("foobar"));
29+
n = TextNode.valueOf("foobar");
30+
assertNodeNumbersForNonNumeric(n);
31+
32+
assertEquals("foobar", n.asText("barf"));
3033

3134
}
3235

src/test/java/com/fasterxml/jackson/databind/node/TestMissingNode.java

+2
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,7 @@ public void testMissing()
2424
assertEquals(4, n.asInt(4));
2525
assertEquals(5L, n.asLong(5));
2626
assertEquals(0.25, n.asDouble(0.25));
27+
28+
assertEquals("foo", n.asText("foo"));
2729
}
2830
}

src/test/java/com/fasterxml/jackson/databind/node/TestNullNode.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ public void testBasicsWithNullNode() throws Exception
3737
assertFalse(n.has("field"));
3838
assertFalse(n.has(3));
3939

40-
// 1.6:
4140
assertNodeNumbersForNonNumeric(n);
41+
42+
// 2.4
43+
assertEquals("foo", n.asText("foo"));
4244
}
4345
}

src/test/java/com/fasterxml/jackson/databind/node/TestNumberNodes.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ public void testInt()
5050
assertEquals(BigDecimal.ONE, n.decimalValue());
5151
assertEquals(BigInteger.ONE, n.bigIntegerValue());
5252
assertEquals("1", n.asText());
53-
53+
// 2.4
54+
assertEquals("1", n.asText("foo"));
55+
5456
assertNodeNumbers(n, 1, 1.0);
5557

5658
assertTrue(IntNode.valueOf(0).canConvertToInt());

src/test/java/com/fasterxml/jackson/databind/node/TestObjectNode.java

+57
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,53 @@ public DataImpl(JsonNode n) {
4646

4747
private final ObjectMapper MAPPER = objectMapper();
4848

49+
public void testSimpleObject() throws Exception
50+
{
51+
String JSON = "{ \"key\" : 1, \"b\" : \"x\" }";
52+
JsonNode root = MAPPER.readTree(JSON);
53+
54+
// basic properties first:
55+
assertFalse(root.isValueNode());
56+
assertTrue(root.isContainerNode());
57+
assertFalse(root.isArray());
58+
assertTrue(root.isObject());
59+
assertEquals(2, root.size());
60+
61+
// Related to [JACKSON-50]:
62+
Iterator<JsonNode> it = root.iterator();
63+
assertNotNull(it);
64+
assertTrue(it.hasNext());
65+
JsonNode n = it.next();
66+
assertNotNull(n);
67+
assertEquals(IntNode.valueOf(1), n);
68+
69+
assertTrue(it.hasNext());
70+
n = it.next();
71+
assertNotNull(n);
72+
assertEquals(TextNode.valueOf("x"), n);
73+
74+
assertFalse(it.hasNext());
75+
76+
// Ok, then, let's traverse via extended interface
77+
ObjectNode obNode = (ObjectNode) root;
78+
Iterator<Map.Entry<String,JsonNode>> fit = obNode.fields();
79+
// we also know that LinkedHashMap is used, i.e. order preserved
80+
assertTrue(fit.hasNext());
81+
Map.Entry<String,JsonNode> en = fit.next();
82+
assertEquals("key", en.getKey());
83+
assertEquals(IntNode.valueOf(1), en.getValue());
84+
85+
assertTrue(fit.hasNext());
86+
en = fit.next();
87+
assertEquals("b", en.getKey());
88+
assertEquals(TextNode.valueOf("x"), en.getValue());
89+
90+
// Plus: we should be able to modify the node via iterator too:
91+
fit.remove();
92+
assertEquals(1, obNode.size());
93+
assertEquals(IntNode.valueOf(1), root.get("key"));
94+
assertNull(root.get("b"));
95+
}
4996
// for [Issue#346]
5097
public void testEmptyNodeAsValue() throws Exception
5198
{
@@ -309,4 +356,14 @@ public void testEqualityWrtOrder() throws Exception
309356
assertTrue(ob1.equals(ob2));
310357
assertTrue(ob2.equals(ob1));
311358
}
359+
360+
public void testSimplePath() throws Exception
361+
{
362+
JsonNode root = MAPPER.readTree("{ \"results\" : { \"a\" : 3 } }");
363+
assertTrue(root.isObject());
364+
JsonNode rnode = root.path("results");
365+
assertNotNull(rnode);
366+
assertTrue(rnode.isObject());
367+
assertEquals(3, rnode.path("a").intValue());
368+
}
312369
}

0 commit comments

Comments
 (0)