package com.fasterxml.jackson.databind.node;
import java.util.*;
import static org.junit.Assert.*;
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.node.BinaryNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.POJONode;
import com.fasterxml.jackson.databind.node.TextNode;
public class TestTreeTraversingParser
extends BaseMapTest
{
static class Person {
public String name;
public int magicNumber;
public List<String> kids;
}
// Helper class for [JACKSON-370]
@JsonIgnoreProperties(ignoreUnknown=true)
public static class Jackson370Bean {
public Inner inner;
}
public static class Inner {
public String value;
}
/*
/**********************************************************
/* Test methods
/**********************************************************
*/
public void testSimple() throws Exception
{
// For convenience, parse tree from JSON first
final String JSON =
"{ \"a\" : 123, \"list\" : [ 12.25, null, true, { }, [ ] ] }";
ObjectMapper m = new ObjectMapper();
JsonNode tree = m.readTree(JSON);
JsonParser jp = tree.traverse();
assertNull(jp.getCurrentToken());
assertNull(jp.getCurrentName());
assertToken(JsonToken.START_OBJECT, jp.nextToken());
assertNull(jp.getCurrentName());
assertEquals("Expected START_OBJECT", JsonToken.START_OBJECT.asString(), jp.getText());
assertToken(JsonToken.FIELD_NAME, jp.nextToken());
assertEquals("a", jp.getCurrentName());
assertEquals("a", jp.getText());
assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
assertEquals("a", jp.getCurrentName());
assertEquals(123, jp.getIntValue());
assertEquals("123", jp.getText());
assertToken(JsonToken.FIELD_NAME, jp.nextToken());
assertEquals("list", jp.getCurrentName());
assertEquals("list", jp.getText());
assertToken(JsonToken.START_ARRAY, jp.nextToken());
assertEquals("list", jp.getCurrentName());
assertEquals(JsonToken.START_ARRAY.asString(), jp.getText());
assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken());
assertNull(jp.getCurrentName());
assertEquals(12.25, jp.getDoubleValue(), 0);
assertEquals("12.25", jp.getText());
assertToken(JsonToken.VALUE_NULL, jp.nextToken());
assertNull(jp.getCurrentName());
assertEquals(JsonToken.VALUE_NULL.asString(), jp.getText());
assertToken(JsonToken.VALUE_TRUE, jp.nextToken());
assertNull(jp.getCurrentName());
assertTrue(jp.getBooleanValue());
assertEquals(JsonToken.VALUE_TRUE.asString(), jp.getText());
assertToken(JsonToken.START_OBJECT, jp.nextToken());
assertNull(jp.getCurrentName());
assertToken(JsonToken.END_OBJECT, jp.nextToken());
assertNull(jp.getCurrentName());
assertToken(JsonToken.START_ARRAY, jp.nextToken());
assertNull(jp.getCurrentName());
assertToken(JsonToken.END_ARRAY, jp.nextToken());
assertNull(jp.getCurrentName());
assertToken(JsonToken.END_ARRAY, jp.nextToken());
assertToken(JsonToken.END_OBJECT, jp.nextToken());
assertNull(jp.getCurrentName());
assertNull(jp.nextToken());
jp.close();
assertTrue(jp.isClosed());
}
public void testArray() throws Exception
{
// For convenience, parse tree from JSON first
ObjectMapper m = new ObjectMapper();
JsonParser jp = m.readTree("[]").traverse();
assertToken(JsonToken.START_ARRAY, jp.nextToken());
assertToken(JsonToken.END_ARRAY, jp.nextToken());
jp.close();
jp = m.readTree("[[]]").traverse();
assertToken(JsonToken.START_ARRAY, jp.nextToken());
assertToken(JsonToken.START_ARRAY, jp.nextToken());
assertToken(JsonToken.END_ARRAY, jp.nextToken());
assertToken(JsonToken.END_ARRAY, jp.nextToken());
jp.close();
jp = m.readTree("[[ 12.1 ]]").traverse();
assertToken(JsonToken.START_ARRAY, jp.nextToken());
assertToken(JsonToken.START_ARRAY, jp.nextToken());
assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken());
assertToken(JsonToken.END_ARRAY, jp.nextToken());
assertToken(JsonToken.END_ARRAY, jp.nextToken());
jp.close();
}
public void testNested() throws Exception
{
// For convenience, parse tree from JSON first
final String JSON =
"{\"coordinates\":[[[-3,\n1],[179.859681,51.175092]]]}"
;
ObjectMapper m = new ObjectMapper();
JsonNode tree = m.readTree(JSON);
JsonParser jp = tree.traverse();
assertToken(JsonToken.START_OBJECT, jp.nextToken());
assertToken(JsonToken.FIELD_NAME, jp.nextToken());
assertToken(JsonToken.START_ARRAY, jp.nextToken());
assertToken(JsonToken.START_ARRAY, jp.nextToken());
assertToken(JsonToken.START_ARRAY, jp.nextToken());
assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken());
assertToken(JsonToken.END_ARRAY, jp.nextToken());
assertToken(JsonToken.START_ARRAY, jp.nextToken());
assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken());
assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken());
assertToken(JsonToken.END_ARRAY, jp.nextToken());
assertToken(JsonToken.END_ARRAY, jp.nextToken());
assertToken(JsonToken.END_ARRAY, jp.nextToken());
assertToken(JsonToken.END_OBJECT, jp.nextToken());
jp.close();
}
/**
* Unit test that verifies that we can (re)parse sample document
* from JSON specification.
*/
public void testSpecDoc() throws Exception
{
ObjectMapper m = new ObjectMapper();
JsonNode tree = m.readTree(SAMPLE_DOC_JSON_SPEC);
JsonParser jp = tree.traverse();
verifyJsonSpecSampleDoc(jp, true);
jp.close();
}
public void testBinaryPojo() throws Exception
{
byte[] inputBinary = new byte[] { 1, 2, 100 };
POJONode n = new POJONode(inputBinary);
JsonParser jp = n.traverse();
assertNull(jp.getCurrentToken());
assertToken(JsonToken.VALUE_EMBEDDED_OBJECT, jp.nextToken());
byte[] data = jp.getBinaryValue();
assertNotNull(data);
assertArrayEquals(inputBinary, data);
Object pojo = jp.getEmbeddedObject();
assertSame(data, pojo);
jp.close();
}
public void testBinaryNode() throws Exception
{
byte[] inputBinary = new byte[] { 0, -5 };
BinaryNode n = new BinaryNode(inputBinary);
JsonParser jp = n.traverse();
assertNull(jp.getCurrentToken());
// exposed as POJO... not as VALUE_STRING
assertToken(JsonToken.VALUE_EMBEDDED_OBJECT, jp.nextToken());
byte[] data = jp.getBinaryValue();
assertNotNull(data);
assertArrayEquals(inputBinary, data);
// but as importantly, can be viewed as base64 encoded thing:
assertEquals("APs=", jp.getText());
assertNull(jp.nextToken());
jp.close();
}
public void testTextAsBinary() throws Exception
{
TextNode n = new TextNode(" APs=\n");
JsonParser jp = n.traverse();
assertNull(jp.getCurrentToken());
assertToken(JsonToken.VALUE_STRING, jp.nextToken());
byte[] data = jp.getBinaryValue();
assertNotNull(data);
assertArrayEquals(new byte[] { 0, -5 }, data);
assertNull(jp.nextToken());
jp.close();
assertTrue(jp.isClosed());
// Also: let's verify we get an exception for garbage...
n = new TextNode("?!??");
jp = n.traverse();
assertToken(JsonToken.VALUE_STRING, jp.nextToken());
try {
jp.getBinaryValue();
} catch (JsonParseException e) {
verifyException(e, "Illegal character");
}
jp.close();
}
/**
* Very simple test case to verify that tree-to-POJO
* conversion works ok
*/
public void testDataBind() throws Exception
{
ObjectMapper m = new ObjectMapper();
JsonNode tree = m.readTree
("{ \"name\" : \"Tatu\", \n"
+"\"magicNumber\" : 42,"
+"\"kids\" : [ \"Leo\", \"Lila\", \"Leia\" ] \n"
+"}");
Person tatu = m.treeToValue(tree, Person.class);
assertNotNull(tatu);
assertEquals(42, tatu.magicNumber);
assertEquals("Tatu", tatu.name);
assertNotNull(tatu.kids);
assertEquals(3, tatu.kids.size());
assertEquals("Leo", tatu.kids.get(0));
assertEquals("Lila", tatu.kids.get(1));
assertEquals("Leia", tatu.kids.get(2));
}
// [JACKSON-370]
public void testSkipChildrenWrt370() throws Exception
{
ObjectMapper o = new ObjectMapper();
ObjectNode n = o.createObjectNode();
n.putObject("inner").put("value", "test");
n.putObject("unknown").putNull("inner");
Jackson370Bean obj = o.readValue(n.traverse(), Jackson370Bean.class);
assertNotNull(obj.inner);
assertEquals("test", obj.inner.value);
}
}