You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2016/08/09 17:15:35 UTC

[14/44] incubator-juneau git commit: Rename CT_* testcases.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/df0f8689/org.apache.juneau/src/test/java/org/apache/juneau/json/CT_CommonParser.java
----------------------------------------------------------------------
diff --git a/org.apache.juneau/src/test/java/org/apache/juneau/json/CT_CommonParser.java b/org.apache.juneau/src/test/java/org/apache/juneau/json/CT_CommonParser.java
deleted file mode 100755
index c600867..0000000
--- a/org.apache.juneau/src/test/java/org/apache/juneau/json/CT_CommonParser.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/***************************************************************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations under the License.
- ***************************************************************************************************************************/
-package org.apache.juneau.json;
-
-import static org.apache.juneau.BeanContext.*;
-import static org.apache.juneau.serializer.SerializerContext.*;
-import static org.junit.Assert.*;
-
-import java.util.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.parser.*;
-import org.junit.*;
-
-@SuppressWarnings({"rawtypes","serial"})
-public class CT_CommonParser {
-
-	//====================================================================================================
-	// testFromSerializer
-	//====================================================================================================
-	@Test
-	public void testFromSerializer() throws Exception {
-		ReaderParser p = JsonParser.DEFAULT.clone().setClassLoader(getClass().getClassLoader());
-
-		Map m = null;
-		m = (Map)p.parse("{a:1}", Object.class);
-		assertEquals(1, m.get("a"));
-		m = (Map)p.parse("{a:1,b:\"foo bar\"}", Object.class);
-		assertEquals(1, m.get("a"));
-		assertEquals("foo bar", m.get("b"));
-		m = (Map)p.parse("{a:1,b:\"foo bar\",c:false}", Object.class);
-		assertEquals(1, m.get("a"));
-		assertEquals(false, m.get("c"));
-		m = (Map)p.parse(" { a : 1 , b : 'foo' , c : false } ", Object.class);
-		assertEquals(1, m.get("a"));
-		assertEquals("foo", m.get("b"));
-		assertEquals(false, m.get("c"));
-
-		m = (Map)p.parse("{x:\"org.apache.juneau.test.Person\",addresses:[{x:\"org.apache.juneau.test.Address\",city:\"city A\",state:\"state A\",street:\"street A\",zip:12345}]}", Object.class);
-		assertEquals("org.apache.juneau.test.Person", m.get("x"));
-		List l = (List)m.get("addresses");
-		assertNotNull(l);
-		m = (Map)l.get(0);
-		assertNotNull(m);
-		assertEquals("org.apache.juneau.test.Address", m.get("x"));
-		assertEquals("city A", m.get("city"));
-		assertEquals("state A", m.get("state"));
-		assertEquals("street A", m.get("street"));
-		assertEquals(12345, m.get("zip"));
-
-		ObjectList jl = (ObjectList)p.parse("[{attribute:'value'},{attribute:'value'}]", Object.class);
-		assertEquals("value", jl.getObjectMap(0).getString("attribute"));
-		assertEquals("value", jl.getObjectMap(1).getString("attribute"));
-
-		// Verify that all the following return null.
-		assertNull(p.parse((CharSequence)null, Object.class));
-		assertNull(p.parse("", Object.class));
-		assertNull(p.parse("   ", Object.class));
-		assertNull(p.parse("   \t", Object.class));
-		assertNull(p.parse("   /*foo*/", Object.class));
-		assertNull(p.parse("   /*foo*/   ", Object.class));
-		assertNull(p.parse("   //foo   ", Object.class));
-
-		try {
-			jl = (ObjectList)p.parse("[{attribute:'value'},{attribute:'value'}]", Object.class);
-			assertEquals("value", jl.getObjectMap(0).getString("attribute"));
-			assertEquals("value", jl.getObjectMap(1).getString("attribute"));
-		} catch (Exception e) {
-			fail(e.getLocalizedMessage());
-		}
-
-		A1 b = new A1();
-		A2 tl = new A2();
-		tl.add(new A3("name0","value0"));
-		tl.add(new A3("name1","value1"));
-		b.list = tl;
-		String json = new JsonSerializer().setProperty(SERIALIZER_addClassAttrs, true).serialize(b);
-		b = (A1)p.parse(json, Object.class);
-		assertEquals("value1", b.list.get(1).value);
-
-		json = JsonSerializer.DEFAULT.serialize(b);
-		b = p.parse(json, A1.class);
-		assertEquals("value1", b.list.get(1).value);
-	}
-
-	public static class A1 {
-		public A2 list;
-	}
-
-	public static class A2 extends LinkedList<A3> {
-	}
-
-	public static class A3 {
-		public String name, value;
-		public A3(){}
-		public A3(String name, String value) {
-			this.name = name;
-			this.value = value;
-		}
-	}
-
-	//====================================================================================================
-	// Correct handling of unknown properties.
-	//====================================================================================================
-	@Test
-	public void testCorrectHandlingOfUnknownProperties() throws Exception {
-		ReaderParser p = new JsonParser().setProperty(BEAN_ignoreUnknownBeanProperties, true);
-		B b;
-
-		String in =  "{a:1,unknown:3,b:2}";
-		b = p.parse(in, B.class);
-		assertEquals(b.a, 1);
-		assertEquals(b.b, 2);
-
-		try {
-			p = new JsonParser();
-			p.parse(in, B.class);
-			fail("Exception expected");
-		} catch (ParseException e) {}
-	}
-
-	public static class B {
-		public int a, b;
-	}
-
-	//====================================================================================================
-	// Writing to Collection properties with no setters.
-	//====================================================================================================
-	@Test
-	public void testCollectionPropertiesWithNoSetters() throws Exception {
-		JsonParser p = JsonParser.DEFAULT;
-		String json = "{ints:[1,2,3],beans:[{a:1,b:2}]}";
-		C t = p.parse(json, C.class);
-		assertEquals(t.getInts().size(), 3);
-		assertEquals(t.getBeans().get(0).b, 2);
-	}
-
-	public static class C {
-		private Collection<Integer> ints = new LinkedList<Integer>();
-		private List<B> beans = new LinkedList<B>();
-		public Collection<Integer> getInts() {
-			return ints;
-		}
-		public List<B> getBeans() {
-			return beans;
-		}
-	}
-
-	//====================================================================================================
-	// Parser listeners.
-	//====================================================================================================
-	@Test
-	public void testParserListeners() throws Exception {
-		final List<String> events = new LinkedList<String>();
-		JsonParser p = new JsonParser().setProperty(BEAN_ignoreUnknownBeanProperties, true);
-		p.addListener(
-			new ParserListener() {
-				@Override /* ParserListener */
-				public <T> void onUnknownProperty(String propertyName, Class<T> beanClass, T bean, int line, int col) {
-					events.add(propertyName + "," + line + "," + col);
-				}
-			}
-		);
-
-		String json = "{a:1,unknownProperty:\"/foo\",b:2}";
-		p.parse(json, B.class);
-		assertEquals(1, events.size());
-		assertEquals("unknownProperty,1,5", events.get(0));
-	}
-}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/df0f8689/org.apache.juneau/src/test/java/org/apache/juneau/json/CT_Json.java
----------------------------------------------------------------------
diff --git a/org.apache.juneau/src/test/java/org/apache/juneau/json/CT_Json.java b/org.apache.juneau/src/test/java/org/apache/juneau/json/CT_Json.java
deleted file mode 100755
index 93e3554..0000000
--- a/org.apache.juneau/src/test/java/org/apache/juneau/json/CT_Json.java
+++ /dev/null
@@ -1,308 +0,0 @@
-/***************************************************************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations under the License.
- ***************************************************************************************************************************/
-package org.apache.juneau.json;
-
-import static org.apache.juneau.TestUtils.*;
-import static org.apache.juneau.json.JsonSerializerContext.*;
-import static org.apache.juneau.serializer.SerializerContext.*;
-import static org.junit.Assert.*;
-
-import java.util.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.json.annotation.*;
-import org.apache.juneau.serializer.*;
-import org.junit.*;
-
-@SuppressWarnings("serial")
-public class CT_Json {
-
-	//====================================================================================================
-	// testBasic
-	//====================================================================================================
-	@Test
-	public void testBasic() throws Exception {
-		Map<String,Object> m = new LinkedHashMap<String,Object>();
-		List<Object> l = new LinkedList<Object>();
-
-		WriterSerializer s1 = new JsonSerializer.Simple().setProperty(SERIALIZER_trimNullProperties, false);
-		WriterSerializer s2 = new JsonSerializer.Simple().setProperty(SERIALIZER_trimNullProperties, false).setProperty(SERIALIZER_quoteChar, '"');
-		String r;
-
-		// Null keys and values
-		m.clear();
-		m.put(null, null);
-		m.put("aaa", "bbb");
-		assertEquals("A1", "{null:null,aaa:'bbb'}", s1.serialize(m));
-
-		// Escapes.
-		// String = ["]
-		m.clear();
-		m.put("x", "[\"]");
-		assertEquals("{x:\"[\\\"]\"}", s2.serialize(m));
-		// String = [\"]
-		// JSON = {x:"\\\""}
-		m.clear();
-		m.put("x", "[\\\"]");
-		assertEquals("{x:\"[\\\\\\\"]\"}", s2.serialize(m));
-
-		// String = [\w[\w\-\.]{3,}\w]
-		// JSON = {x:"\\w[\\w\\-\\.]{3,}\\w"}
-		m.clear();
-		r = "\\w[\\w\\-\\.]{3,}\\w";
-		m.put("x", r);
-		assertEquals("{x:\"\\\\w[\\\\w\\\\-\\\\.]{3,}\\\\w\"}", s2.serialize(m));
-		assertEquals(r, new ObjectMap(s2.serialize(m)).getString("x"));
-
-		// String = [foo\bar]
-		// JSON = {x:"foo\\bar"}
-		m.clear();
-		m.put("x", "foo\\bar");
-		assertEquals("{x:\"foo\\\\bar\"}", s2.serialize(m));
-
-		m.clear();
-		m.put("null", null);
-		m.put("aaa", "bbb");
-		assertEquals("A2", "{'null':null,aaa:'bbb'}", s1.serialize(m));
-
-		m.clear();
-		m.put(null, "null");
-		m.put("aaa", "bbb");
-		assertEquals("A3", "{null:'null',aaa:'bbb'}", s1.serialize(m));
-
-		// Arrays
-		m.clear();
-		l.clear();
-		m.put("J", "f1");
-		m.put("B", "b");
-		m.put("C", "c");
-		l.add("1");
-		l.add("2");
-		l.add("3");
-		Object o = new Object[] { m, l };
-		Object o2 = new Object[] { o, "foo", "bar", new Integer(1), new Boolean(false), new Float(1.2), null };
-		assertEquals("K1", "[[{J:'f1',B:'b',C:'c'},['1','2','3']],'foo','bar',1,false,1.2,null]", s1.serialize(o2));
-	}
-
-	@Test
-	public void testReservedKeywordAttributes() throws Exception {
-		Map<String,Object> m = new LinkedHashMap<String,Object>();
-
-		// Keys with reserved names.
-		for (String attr : new String[]{"","true","false","null","try","123","1x","-123",".123"}) {
-			m.clear();
-			m.put(attr,1);
-			assertObjectEquals("{'"+attr+"':1}", m);
-		}
-	}
-
-	//====================================================================================================
-	// Validate various backslashes in strings.
-	//====================================================================================================
-	@Test
-	public void testBackslashesInStrings() throws Exception {
-		JsonSerializer s = new JsonSerializer.Simple().setProperty(SERIALIZER_trimNullProperties, false).setProperty(SERIALIZER_quoteChar, '"');
-		String r, r2;
-
-		// [\\]
-		r = "\\";
-		r2 = s.serialize(r);
-		assertEquals(r2, "\"\\\\\"");
-		assertEquals(JsonParser.DEFAULT.parse(r2, Object.class), r);
-
-		// [\b\f\n\t]
-		r = "\b\f\n\t";
-		r2 = s.serialize(r);
-		assertEquals("\"\\b\\f\\n\\t\"", r2);
-		assertEquals(r, JsonParser.DEFAULT.parse(r2, Object.class));
-
-		// Special JSON case:  Forward slashes can OPTIONALLY be escaped.
-		// [\/]
-		assertEquals(JsonParser.DEFAULT.parse("\"\\/\"", Object.class), "/");
-
-		// Unicode
-		r = "\u1234\u1ABC\u1abc";
-		r2 = s.serialize(r);
-		assertEquals("\"\u1234\u1ABC\u1abc\"", r2);
-
-		assertEquals("\u1234", JsonParser.DEFAULT.parse("\"\\u1234\"", Object.class));
-	}
-
-	//====================================================================================================
-	// Indentation
-	//====================================================================================================
-	@Test
-	public void testIndentation() throws Exception {
-		ObjectMap m = new ObjectMap("{J:{B:['c',{D:'e'},['f',{G:'h'},1,false]]},I:'j'}");
-		String e = ""
-			+ "{"
-			+ "\n	J: {"
-			+ "\n		B: ["
-			+ "\n			'c', "
-			+ "\n			{"
-			+ "\n				D: 'e'"
-			+ "\n			}, "
-			+ "\n			["
-			+ "\n				'f', "
-			+ "\n				{"
-			+ "\n					G: 'h'"
-			+ "\n				}, "
-			+ "\n				1, "
-			+ "\n				false"
-			+ "\n			]"
-			+ "\n		]"
-			+ "\n	}, "
-			+ "\n	I: 'j'"
-			+ "\n}";
-		assertEquals(e, JsonSerializer.DEFAULT_LAX_READABLE.serialize(m));
-	}
-
-	//====================================================================================================
-	// Escaping double quotes
-	//====================================================================================================
-	@Test
-	public void testEscapingDoubleQuotes() throws Exception {
-		JsonSerializer s = JsonSerializer.DEFAULT;
-		String r = s.serialize(new ObjectMap().append("f1", "x'x\"x"));
-		assertEquals("{\"f1\":\"x'x\\\"x\"}", r);
-		JsonParser p = JsonParser.DEFAULT;
-		assertEquals("x'x\"x", p.parse(r, ObjectMap.class).getString("f1"));
-	}
-
-	//====================================================================================================
-	// Escaping single quotes
-	//====================================================================================================
-	@Test
-	public void testEscapingSingleQuotes() throws Exception {
-		JsonSerializer s = JsonSerializer.DEFAULT_LAX;
-		String r = s.serialize(new ObjectMap().append("f1", "x'x\"x"));
-		assertEquals("{f1:'x\\'x\"x'}", r);
-		JsonParser p = JsonParser.DEFAULT;
-		assertEquals("x'x\"x", p.parse(r, ObjectMap.class).getString("f1"));
-	}
-
-	//====================================================================================================
-	// testWrapperAttrAnnotationOnBean
-	//====================================================================================================
-	@Test
-	@SuppressWarnings("unchecked")
-	public void testWrapperAttrAnnotationOnBean() throws Exception {
-		JsonSerializer s = JsonSerializer.DEFAULT_LAX;
-		JsonParser p = JsonParser.DEFAULT;
-		String r;
-
-		A t = A.create();
-		r = s.serialize(t);
-		assertEquals("{foo:{f1:1}}", r);
-		t = p.parse(r, A.class);
-		assertEquals(1, t.f1);
-
-		Map<String,A> m = new LinkedHashMap<String,A>();
-		m.put("bar", A.create());
-		r = s.serialize(m);
-		assertEquals("{bar:{foo:{f1:1}}}", r);
-
-		m = p.parseMap(r, LinkedHashMap.class, String.class, A.class);
-		assertEquals(1, m.get("bar").f1);
-	}
-
-	@Json(wrapperAttr="foo")
-	public static class A {
-		public int f1;
-
-		static A create() {
-			A a = new A();
-			a.f1 = 1;
-			return a;
-		}
-	}
-
-	//====================================================================================================
-	// testWrapperAttrAnnotationOnNonBean
-	//====================================================================================================
-	@Test
-	@SuppressWarnings("unchecked")
-	public void testWrapperAttrAnnotationOnNonBean() throws Exception {
-		JsonSerializer s = JsonSerializer.DEFAULT_LAX;
-		JsonParser p = JsonParser.DEFAULT;
-		String r;
-
-		B t = B.create();
-		r = s.serialize(t);
-		assertEquals("{foo:'1'}", r);
-		t = p.parse(r, B.class);
-		assertEquals(1, t.f1);
-
-		Map<String,B> m = new LinkedHashMap<String,B>();
-		m.put("bar", B.create());
-		r = s.serialize(m);
-		assertEquals("{bar:{foo:'1'}}", r);
-
-		m = p.parseMap(r, LinkedHashMap.class, String.class, B.class);
-		assertEquals(1, m.get("bar").f1);
-	}
-
-	@Json(wrapperAttr="foo")
-	public static class B {
-		int f1;
-
-		static B create() {
-			B b = new B();
-			b.f1 = 1;
-			return b;
-		}
-
-		@Override /* Object */
-		public String toString() {
-			return String.valueOf(f1);
-		}
-
-		public static B valueOf(String s) {
-			B b = new B();
-			b.f1 = Integer.parseInt(s);
-			return b;
-		}
-	}
-
-	//====================================================================================================
-	// testAddClassAttrs
-	//====================================================================================================
-	@Test
-	public void testAddClassAttrs() throws Exception {
-		JsonSerializer s = new JsonSerializer().setProperty(SERIALIZER_addClassAttrs, true);
-		Map<String,Object> o = new HashMap<String,Object>();
-		o.put("c", new C());
-		assertEquals("{\"c\":{\"_class\":\"org.apache.juneau.json.CT_Json$C\",\"items\":[]}}", s.serialize(o));
-	}
-
-	public static class C extends LinkedList<String> {
-	}
-
-	//====================================================================================================
-	// testEscapeSolidus
-	//====================================================================================================
-	@Test
-	public void testEscapeSolidus() throws Exception {
-		JsonSerializer s = new JsonSerializer().setProperty(JSON_escapeSolidus, false);
-		String r = s.serialize("foo/bar");
-		assertEquals("\"foo/bar\"", r);
-		r = JsonParser.DEFAULT.parse(r, String.class);
-		assertEquals("foo/bar", r);
-
-		s = new JsonSerializer().setProperty(JSON_escapeSolidus, true);
-		r = s.serialize("foo/bar");
-		assertEquals("\"foo\\/bar\"", r);
-		r = JsonParser.DEFAULT.parse(r, String.class);
-		assertEquals("foo/bar", r);
-	}
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/df0f8689/org.apache.juneau/src/test/java/org/apache/juneau/json/CT_JsonParser.java
----------------------------------------------------------------------
diff --git a/org.apache.juneau/src/test/java/org/apache/juneau/json/CT_JsonParser.java b/org.apache.juneau/src/test/java/org/apache/juneau/json/CT_JsonParser.java
deleted file mode 100755
index e00aa77..0000000
--- a/org.apache.juneau/src/test/java/org/apache/juneau/json/CT_JsonParser.java
+++ /dev/null
@@ -1,331 +0,0 @@
-/***************************************************************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations under the License.
- ***************************************************************************************************************************/
-package org.apache.juneau.json;
-
-import static org.junit.Assert.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.parser.*;
-import org.apache.juneau.serializer.*;
-import org.junit.*;
-
-@SuppressWarnings("hiding")
-public class CT_JsonParser {
-
-	private static final JsonParser p = JsonParser.DEFAULT;
-	private static final JsonParser sp = JsonParser.DEFAULT_STRICT;
-
-
-	//====================================================================================================
-	// Test invalid input
-	//====================================================================================================
-	@Test
-	public void testInvalidJson() {
-		try {
-			p.parse("{\na:1,\nb:xxx\n}", Object.class);
-			fail("Exception expected.");
-		} catch (ParseException e) {}
-	}
-
-	@Test
-	public void testNonExistentAttribute() throws Exception {
-		String json = "{foo:,bar:}";
-		ObjectMap m = p.parse(json, ObjectMap.class);
-		assertEquals("{foo:null,bar:null}", m.toString());
-	}
-
-	@Test
-	public void testNonStringAsString() throws Exception {
-		String json = "123";
-		String s;
-
-		// Strict mode does not allow unquoted values.
-		try {
-			sp.parse(json, String.class);
-			fail("Exception expected");
-		} catch (Exception e) {
-			assertTrue(e.getMessage().contains("Did not find quote character"));
-		}
-
-		s = p.parse(json, String.class);
-		assertEquals("123", s);
-
-		json = " 123 ";
-		// Strict mode does not allow unquoted values.
-		try {
-			sp.parse(json, String.class);
-			fail("Exception expected");
-		} catch (Exception e) {
-			assertTrue(e.getMessage().contains("Did not find quote character"));
-		}
-
-		s = p.parse(json, String.class);
-		assertEquals("123", s);
-
-		json = "{\"fa\":123}";
-		try {
-			sp.parse(json, A.class);
-			fail("Exception expected");
-		} catch (Exception e) {
-			assertTrue(e.getMessage().contains("Did not find quote character"));
-		}
-
-		A a = p.parse(json, A.class);
-		assertEquals("123", a.fa);
-
-		json = " { \"fa\" : 123 } ";
-		try {
-			sp.parse(json, A.class);
-			fail("Exception expected");
-		} catch (Exception e) {
-			assertTrue(e.getMessage().contains("Did not find quote character"));
-		}
-
-		a = p.parse(json, A.class);
-		assertEquals("123", a.fa);
-
-		json = "'123'";
-		try {
-			sp.parse(json, String.class);
-			fail("Exception expected");
-		} catch (Exception e) {
-			assertTrue(e.getMessage().contains("Invalid quote character"));
-		}
-	}
-
-	public static class A {
-		public String fa;
-	}
-
-	@Test
-	public void testCognosJson() throws Exception {
-		String json = TestUtils.readFile(getClass().getResource("/json/BrokenCognosOutput.txt").getPath());
-		p.parse(json, ObjectMap.class);
-	}
-
-	@Test
-	public void testStrictMode() throws Exception {
-		JsonParser p = sp;
-
-		// Missing attribute values.
-		String json = "{\"foo\":,\"bar\":}";
-		try {
-			p.parse(json, ObjectMap.class);
-			fail("Exception expected");
-		} catch (ParseException e) {
-			assertEquals("Parse exception occurred at {currentClass:'Object',line:1,column:7}.  Missing value detected.", e.getRootCause().getMessage());
-		}
-
-		// Single quoted values.
-		json = "{\"foo\":'bar'}";
-		try {
-			p.parse(json, ObjectMap.class);
-			fail("Exception expected");
-		} catch (ParseException e) {
-			assertEquals("Parse exception occurred at {currentClass:'Object',line:1,column:8}.  Invalid quote character \"'\" being used.", e.getRootCause().getMessage());
-		}
-
-		// Single quoted attribute name.
-		json = "{'foo':\"bar\"}";
-		try {
-			p.parse(json, ObjectMap.class);
-			fail("Exception expected");
-		} catch (ParseException e) {
-			assertEquals("Parse exception occurred at {currentClass:'ObjectMap<String,Object>',line:1,column:2}.  Invalid quote character \"'\" being used.", e.getRootCause().getMessage());
-		}
-
-		// Unquoted attribute name.
-		json = "{foo:\"bar\"}";
-		try {
-			p.parse(json, ObjectMap.class);
-			fail("Exception expected");
-		} catch (ParseException e) {
-			assertEquals("Parse exception occurred at {currentClass:'ObjectMap<String,Object>',line:1,column:1}.  Unquoted attribute detected.", e.getRootCause().getMessage());
-		}
-
-		// Concatenated string
-		json = "{\"foo\":\"bar\"+\"baz\"}";
-		try {
-			p.parse(json, ObjectMap.class);
-			fail("Exception expected");
-		} catch (ParseException e) {
-			assertEquals("Parse exception occurred at {currentClass:'Object',line:1,column:12}.  String concatenation detected.", e.getRootCause().getMessage());
-		}
-
-		// Concatenated string 2
-		json = "{\"foo\":\"bar\" + \"baz\"}";
-		try {
-			p.parse(json, ObjectMap.class);
-			fail("Exception expected");
-		} catch (ParseException e) {
-			assertEquals("Parse exception occurred at {currentClass:'Object',line:1,column:13}.  String concatenation detected.", e.getRootCause().getMessage());
-		}
-
-		json = "{\"foo\":/*comment*/\"bar\"}";
-		try {
-			p.parse(json, ObjectMap.class);
-			fail("Exception expected");
-		} catch (ParseException e) {
-			assertEquals("Parse exception occurred at {currentClass:'ObjectMap<String,Object>',line:1,column:8}.  Javascript comment detected.", e.getRootCause().getMessage());
-		}
-	}
-
-	/**
-	 * JSON numbers and booleans should be representable as strings and converted accordingly.
-	 */
-	@Test
-	public void testPrimitivesAsStrings() throws Exception {
-		String json;
-		ReaderParser p = JsonParser.DEFAULT;
-		WriterSerializer s = JsonSerializer.DEFAULT_LAX;
-
-		json = "{f1:'1',f2:'1',f3:'true',f4:'true',f5:'1',f6:'1',f7:'1',f8:'1',f9:'1',f10:'1'}";
-		B b = p.parse(json, B.class);
-		assertEquals("{f1:1,f2:1,f3:true,f4:true,f5:1.0,f6:1.0,f7:1,f8:1,f9:1,f10:1}", s.toString(b));
-
-		json = "{f1:'',f2:'',f3:'',f4:'',f5:'',f6:'',f7:'',f8:'',f9:'',f10:''}";
-		b = p.parse(json, B.class);
-		assertEquals("{f1:0,f2:0,f3:false,f4:false,f5:0.0,f6:0.0,f7:0,f8:0,f9:0,f10:0}", s.toString(b));
-	}
-
-	public static class B {
-		public int f1;
-		public Integer f2;
-		public boolean f3;
-		public Boolean f4;
-		public float f5;
-		public Float f6;
-		public long f7;
-		public Long f8;
-		public byte f9;
-		public Byte f10;
-	}
-
-	//====================================================================================================
-	// testInvalidJsonNumbers
-	// Lax parser allows octal and hexadecimal numbers.  Strict parser does not.
-	//====================================================================================================
-	@Test
-	public void testInvalidJsonNumbers() throws Exception {
-		JsonParser p1 = JsonParser.DEFAULT;
-		JsonParser p2 = JsonParser.DEFAULT_STRICT;
-		Number r;
-
-		// Lax allows blank strings interpreted as 0, strict does not.
-		String s = "\"\"";
-		r = p1.parse(s, Number.class);
-		assertEquals(0, r.intValue());
-		assertTrue(r instanceof Integer);
-		try {
-			r = p2.parse(s, Number.class);
-			fail("Exception expected");
-		} catch (ParseException e) {
-			assertTrue(e.getMessage().endsWith("Invalid JSON number ''"));
-		}
-
-		// Either should allow 0 or -0.
-		s = "0";
-		r = p1.parse(s, Number.class);
-		assertEquals(0, r.intValue());
-		assertTrue(r instanceof Integer);
-		r = p2.parse(s, Number.class);
-		assertEquals(0, r.intValue());
-		assertTrue(r instanceof Integer);
-
-		s = "-0";
-		r = p1.parse(s, Number.class);
-		assertEquals(0, r.intValue());
-		assertTrue(r instanceof Integer);
-		r = p2.parse(s, Number.class);
-		assertEquals(0, r.intValue());
-		assertTrue(r instanceof Integer);
-
-		// Lax allows 0123 and -0123, strict does not.
-		s = "0123";
-		r = p1.parse(s, Number.class);
-		assertEquals(0123, r.intValue());
-		assertTrue(r instanceof Integer);
-		try {
-			r = p2.parse(s, Number.class);
-			fail("Exception expected");
-		} catch (ParseException e) {
-			assertTrue(e.getMessage().endsWith("Invalid JSON number '0123'"));
-		}
-		s = "-0123";
-		r = p1.parse(s, Number.class);
-		assertEquals(-0123, r.intValue());
-		assertTrue(r instanceof Integer);
-		try {
-			r = p2.parse(s, Number.class);
-			fail("Exception expected");
-		} catch (ParseException e) {
-			assertTrue(e.getMessage().endsWith("Invalid JSON number '-0123'"));
-		}
-
-		// Lax allows 0x123 and -0x123, strict does not.
-		s = "0x123";
-		r = p1.parse(s, Number.class);
-		assertEquals(0x123, r.intValue());
-		assertTrue(r instanceof Integer);
-		try {
-			r = p2.parse(s, Number.class);
-			fail("Exception expected");
-		} catch (ParseException e) {
-			assertTrue(e.getMessage().endsWith("Invalid JSON number '0x123'"));
-		}
-		s = "-0x123";
-		r = p1.parse(s, Number.class);
-		assertEquals(-0x123, r.intValue());
-		assertTrue(r instanceof Integer);
-		try {
-			r = p2.parse(s, Number.class);
-			fail("Exception expected");
-		} catch (ParseException e) {
-			assertTrue(e.getMessage().endsWith("Invalid JSON number '-0x123'"));
-		}
-	}
-
-	//====================================================================================================
-	// testUnquotedStrings
-	// Lax parser allows unquoted strings if POJO can be converted from a string.
-	//====================================================================================================
-	@Test
-	public void testUnquotedStrings() throws Exception {
-		JsonParser p1 = JsonParser.DEFAULT;
-		JsonParser p2 = JsonParser.DEFAULT_STRICT;
-
-		String s = "foobar";
-		C c = p1.parse(s, C.class);
-		assertEquals("f=foobar", c.toString());
-
-		try {
-			p2.parse(s, C.class);
-			fail("Exception expected");
-		} catch (ParseException e) {
-			// OK
-		}
-	}
-
-	public static class C {
-		String f;
-		public static C valueOf(String s) {
-			C c = new C();
-			c.f = s;
-			return c;
-		}
-		@Override /* Object */
-		public String toString() {
-			return "f="+f;
-		}
-	}
-}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/df0f8689/org.apache.juneau/src/test/java/org/apache/juneau/json/CT_JsonSchema.java
----------------------------------------------------------------------
diff --git a/org.apache.juneau/src/test/java/org/apache/juneau/json/CT_JsonSchema.java b/org.apache.juneau/src/test/java/org/apache/juneau/json/CT_JsonSchema.java
deleted file mode 100755
index a22412c..0000000
--- a/org.apache.juneau/src/test/java/org/apache/juneau/json/CT_JsonSchema.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/***************************************************************************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations under the License.
- ***************************************************************************************************************************/
-package org.apache.juneau.json;
-
-import static org.junit.Assert.*;
-
-import org.junit.*;
-
-public class CT_JsonSchema {
-
-	//====================================================================================================
-	// Primitive objects
-	//====================================================================================================
-	@Test
-	public void testBasic() throws Exception {
-
-		JsonSchemaSerializer s = JsonSerializer.DEFAULT_LAX.getSchemaSerializer();
-
-		Object o = new String();
-		assertEquals("{type:'string',description:'java.lang.String'}", s.serialize(o));
-
-		o = new Integer(123);
-		assertEquals("{type:'number',description:'java.lang.Integer'}", s.serialize(o));
-
-		o = new Float(123);
-		assertEquals("{type:'number',description:'java.lang.Float'}", s.serialize(o));
-
-		o = new Double(123);
-		assertEquals("{type:'number',description:'java.lang.Double'}", s.serialize(o));
-
-		o = Boolean.TRUE;
-		assertEquals("{type:'boolean',description:'java.lang.Boolean'}", s.serialize(o));
-	}
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/df0f8689/org.apache.juneau/src/test/java/org/apache/juneau/json/CommonParserTest.java
----------------------------------------------------------------------
diff --git a/org.apache.juneau/src/test/java/org/apache/juneau/json/CommonParserTest.java b/org.apache.juneau/src/test/java/org/apache/juneau/json/CommonParserTest.java
new file mode 100755
index 0000000..c809254
--- /dev/null
+++ b/org.apache.juneau/src/test/java/org/apache/juneau/json/CommonParserTest.java
@@ -0,0 +1,180 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations under the License.
+ ***************************************************************************************************************************/
+package org.apache.juneau.json;
+
+import static org.apache.juneau.BeanContext.*;
+import static org.apache.juneau.serializer.SerializerContext.*;
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.parser.*;
+import org.junit.*;
+
+@SuppressWarnings({"rawtypes","serial"})
+public class CommonParserTest {
+
+	//====================================================================================================
+	// testFromSerializer
+	//====================================================================================================
+	@Test
+	public void testFromSerializer() throws Exception {
+		ReaderParser p = JsonParser.DEFAULT.clone().setClassLoader(getClass().getClassLoader());
+
+		Map m = null;
+		m = (Map)p.parse("{a:1}", Object.class);
+		assertEquals(1, m.get("a"));
+		m = (Map)p.parse("{a:1,b:\"foo bar\"}", Object.class);
+		assertEquals(1, m.get("a"));
+		assertEquals("foo bar", m.get("b"));
+		m = (Map)p.parse("{a:1,b:\"foo bar\",c:false}", Object.class);
+		assertEquals(1, m.get("a"));
+		assertEquals(false, m.get("c"));
+		m = (Map)p.parse(" { a : 1 , b : 'foo' , c : false } ", Object.class);
+		assertEquals(1, m.get("a"));
+		assertEquals("foo", m.get("b"));
+		assertEquals(false, m.get("c"));
+
+		m = (Map)p.parse("{x:\"org.apache.juneau.test.Person\",addresses:[{x:\"org.apache.juneau.test.Address\",city:\"city A\",state:\"state A\",street:\"street A\",zip:12345}]}", Object.class);
+		assertEquals("org.apache.juneau.test.Person", m.get("x"));
+		List l = (List)m.get("addresses");
+		assertNotNull(l);
+		m = (Map)l.get(0);
+		assertNotNull(m);
+		assertEquals("org.apache.juneau.test.Address", m.get("x"));
+		assertEquals("city A", m.get("city"));
+		assertEquals("state A", m.get("state"));
+		assertEquals("street A", m.get("street"));
+		assertEquals(12345, m.get("zip"));
+
+		ObjectList jl = (ObjectList)p.parse("[{attribute:'value'},{attribute:'value'}]", Object.class);
+		assertEquals("value", jl.getObjectMap(0).getString("attribute"));
+		assertEquals("value", jl.getObjectMap(1).getString("attribute"));
+
+		// Verify that all the following return null.
+		assertNull(p.parse((CharSequence)null, Object.class));
+		assertNull(p.parse("", Object.class));
+		assertNull(p.parse("   ", Object.class));
+		assertNull(p.parse("   \t", Object.class));
+		assertNull(p.parse("   /*foo*/", Object.class));
+		assertNull(p.parse("   /*foo*/   ", Object.class));
+		assertNull(p.parse("   //foo   ", Object.class));
+
+		try {
+			jl = (ObjectList)p.parse("[{attribute:'value'},{attribute:'value'}]", Object.class);
+			assertEquals("value", jl.getObjectMap(0).getString("attribute"));
+			assertEquals("value", jl.getObjectMap(1).getString("attribute"));
+		} catch (Exception e) {
+			fail(e.getLocalizedMessage());
+		}
+
+		A1 b = new A1();
+		A2 tl = new A2();
+		tl.add(new A3("name0","value0"));
+		tl.add(new A3("name1","value1"));
+		b.list = tl;
+		String json = new JsonSerializer().setProperty(SERIALIZER_addClassAttrs, true).serialize(b);
+		b = (A1)p.parse(json, Object.class);
+		assertEquals("value1", b.list.get(1).value);
+
+		json = JsonSerializer.DEFAULT.serialize(b);
+		b = p.parse(json, A1.class);
+		assertEquals("value1", b.list.get(1).value);
+	}
+
+	public static class A1 {
+		public A2 list;
+	}
+
+	public static class A2 extends LinkedList<A3> {
+	}
+
+	public static class A3 {
+		public String name, value;
+		public A3(){}
+		public A3(String name, String value) {
+			this.name = name;
+			this.value = value;
+		}
+	}
+
+	//====================================================================================================
+	// Correct handling of unknown properties.
+	//====================================================================================================
+	@Test
+	public void testCorrectHandlingOfUnknownProperties() throws Exception {
+		ReaderParser p = new JsonParser().setProperty(BEAN_ignoreUnknownBeanProperties, true);
+		B b;
+
+		String in =  "{a:1,unknown:3,b:2}";
+		b = p.parse(in, B.class);
+		assertEquals(b.a, 1);
+		assertEquals(b.b, 2);
+
+		try {
+			p = new JsonParser();
+			p.parse(in, B.class);
+			fail("Exception expected");
+		} catch (ParseException e) {}
+	}
+
+	public static class B {
+		public int a, b;
+	}
+
+	//====================================================================================================
+	// Writing to Collection properties with no setters.
+	//====================================================================================================
+	@Test
+	public void testCollectionPropertiesWithNoSetters() throws Exception {
+		JsonParser p = JsonParser.DEFAULT;
+		String json = "{ints:[1,2,3],beans:[{a:1,b:2}]}";
+		C t = p.parse(json, C.class);
+		assertEquals(t.getInts().size(), 3);
+		assertEquals(t.getBeans().get(0).b, 2);
+	}
+
+	public static class C {
+		private Collection<Integer> ints = new LinkedList<Integer>();
+		private List<B> beans = new LinkedList<B>();
+		public Collection<Integer> getInts() {
+			return ints;
+		}
+		public List<B> getBeans() {
+			return beans;
+		}
+	}
+
+	//====================================================================================================
+	// Parser listeners.
+	//====================================================================================================
+	@Test
+	public void testParserListeners() throws Exception {
+		final List<String> events = new LinkedList<String>();
+		JsonParser p = new JsonParser().setProperty(BEAN_ignoreUnknownBeanProperties, true);
+		p.addListener(
+			new ParserListener() {
+				@Override /* ParserListener */
+				public <T> void onUnknownProperty(String propertyName, Class<T> beanClass, T bean, int line, int col) {
+					events.add(propertyName + "," + line + "," + col);
+				}
+			}
+		);
+
+		String json = "{a:1,unknownProperty:\"/foo\",b:2}";
+		p.parse(json, B.class);
+		assertEquals(1, events.size());
+		assertEquals("unknownProperty,1,5", events.get(0));
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/df0f8689/org.apache.juneau/src/test/java/org/apache/juneau/json/CommonTest.java
----------------------------------------------------------------------
diff --git a/org.apache.juneau/src/test/java/org/apache/juneau/json/CommonTest.java b/org.apache.juneau/src/test/java/org/apache/juneau/json/CommonTest.java
new file mode 100755
index 0000000..c64fb25
--- /dev/null
+++ b/org.apache.juneau/src/test/java/org/apache/juneau/json/CommonTest.java
@@ -0,0 +1,501 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations under the License.
+ ***************************************************************************************************************************/
+package org.apache.juneau.json;
+
+import static org.apache.juneau.BeanContext.*;
+import static org.apache.juneau.TestUtils.*;
+import static org.apache.juneau.serializer.SerializerContext.*;
+import static org.junit.Assert.*;
+
+import java.net.*;
+import java.net.URI;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.serializer.*;
+import org.apache.juneau.testbeans.*;
+import org.junit.*;
+
+@SuppressWarnings({"serial"})
+public class CommonTest {
+
+	//====================================================================================================
+	// Trim nulls from beans
+	//====================================================================================================
+	@Test
+	public void testTrimNullsFromBeans() throws Exception {
+		JsonSerializer s = new JsonSerializer.Simple();
+		JsonParser p = JsonParser.DEFAULT;
+		A t1 = A.create(), t2;
+
+		s.setProperty(SERIALIZER_trimNullProperties, false);
+		String r = s.serialize(t1);
+		assertEquals("{s1:null,s2:'s2'}", r);
+		t2 = p.parse(r, A.class);
+		assertEqualObjects(t1, t2);
+
+		s.setProperty(SERIALIZER_trimNullProperties, true);
+		r = s.serialize(t1);
+		assertEquals("{s2:'s2'}", r);
+		t2 = p.parse(r, A.class);
+		assertEqualObjects(t1, t2);
+	}
+
+	public static class A {
+		public String s1, s2;
+
+		public static A create() {
+			A t = new A();
+			t.s2 = "s2";
+			return t;
+		}
+	}
+
+	//====================================================================================================
+	// Trim empty maps
+	//====================================================================================================
+	@Test
+	public void testTrimEmptyMaps() throws Exception {
+		JsonSerializer s = new JsonSerializer.Simple();
+		JsonParser p = JsonParser.DEFAULT;
+		B t1 = B.create(), t2;
+		String r;
+
+		s.setProperty(SERIALIZER_trimEmptyMaps, false);
+		r = s.serialize(t1);
+		assertEquals("{f1:{},f2:{f2a:null,f2b:{s2:'s2'}}}", r);
+		t2 = p.parse(r, B.class);
+		assertEqualObjects(t1, t2);
+
+		s.setProperty(SERIALIZER_trimEmptyMaps, true);
+		r = s.serialize(t1);
+		assertEquals("{f2:{f2a:null,f2b:{s2:'s2'}}}", r);
+		t2 = p.parse(r, B.class);
+		assertNull(t2.f1);
+	}
+
+	public static class B {
+		public TreeMap<String,A> f1, f2;
+
+		public static B create() {
+			B t = new B();
+			t.f1 = new TreeMap<String,A>();
+			t.f2 = new TreeMap<String,A>(){{put("f2a",null);put("f2b",A.create());}};
+			return t;
+		}
+	}
+
+	//====================================================================================================
+	// Trim empty lists
+	//====================================================================================================
+	@Test
+	public void testTrimEmptyLists() throws Exception {
+		JsonSerializer s = new JsonSerializer.Simple();
+		JsonParser p = JsonParser.DEFAULT;
+		C t1 = C.create(), t2;
+		String r;
+
+		s.setProperty(SERIALIZER_trimEmptyLists, false);
+		r = s.serialize(t1);
+		assertEquals("{f1:[],f2:[null,{s2:'s2'}]}", r);
+		t2 = p.parse(r, C.class);
+		assertEqualObjects(t1, t2);
+
+		s.setProperty(SERIALIZER_trimEmptyLists, true);
+		r = s.serialize(t1);
+		assertEquals("{f2:[null,{s2:'s2'}]}", r);
+		t2 = p.parse(r, C.class);
+		assertNull(t2.f1);
+	}
+
+	public static class C {
+		public List<A> f1, f2;
+
+		public static C create() {
+			C t = new C();
+			t.f1 = new LinkedList<A>();
+			t.f2 = new LinkedList<A>(){{add(null);add(A.create());}};
+			return t;
+		}
+	}
+
+	//====================================================================================================
+	// Trim empty arrays
+	//====================================================================================================
+	@Test
+	public void testTrimEmptyArrays() throws Exception {
+		JsonSerializer s = new JsonSerializer.Simple();
+		JsonParser p = JsonParser.DEFAULT;
+		D t1 = D.create(), t2;
+		String r;
+
+		s.setProperty(SERIALIZER_trimEmptyLists, false);
+		r = s.serialize(t1);
+		assertEquals("{f1:[],f2:[null,{s2:'s2'}]}", r);
+		t2 = p.parse(r, D.class);
+		assertEqualObjects(t1, t2);
+
+		s.setProperty(SERIALIZER_trimEmptyLists, true);
+		r = s.serialize(t1);
+		assertEquals("{f2:[null,{s2:'s2'}]}", r);
+		t2 = p.parse(r, D.class);
+		assertNull(t2.f1);
+	}
+
+	public static class D {
+		public A[] f1, f2;
+
+		public static D create() {
+			D t = new D();
+			t.f1 = new A[]{};
+			t.f2 = new A[]{null, A.create()};
+			return t;
+		}
+	}
+
+	//====================================================================================================
+	// @BeanProperty.properties annotation.
+	//====================================================================================================
+	@Test
+	public void testBeanPropertyProperies() throws Exception {
+		JsonSerializer s = JsonSerializer.DEFAULT_LAX;
+		E1 t = new E1();
+		String r;
+
+		r = s.serialize(t);
+		assertEquals("{x1:{f1:1},x2:{f1:1},x3:[{f1:1}],x4:[{f1:1}],x5:[{f1:1}],x6:[{f1:1}]}", r);
+		r = s.getSchemaSerializer().serialize(t);
+		assertTrue(r.indexOf("f2") == -1);
+	}
+
+	public static class E1 {
+		@BeanProperty(properties={"f1"}) public E2 x1 = new E2();
+		@BeanProperty(properties={"f1"}) public Map<String,Integer> x2 = new LinkedHashMap<String,Integer>() {{
+			put("f1",1); put("f2",2);
+		}};
+		@BeanProperty(properties={"f1"}) public E2[] x3 = {new E2()};
+		@BeanProperty(properties={"f1"}) public List<E2> x4 = new LinkedList<E2>() {{
+			add(new E2());
+		}};
+		@BeanProperty(properties={"f1"}) public ObjectMap[] x5 = {new ObjectMap().append("f1",1).append("f2",2)};
+		@BeanProperty(properties={"f1"}) public List<ObjectMap> x6 = new LinkedList<ObjectMap>() {{
+			add(new ObjectMap().append("f1",1).append("f2",2));
+		}};
+	}
+
+	public static class E2 {
+		public int f1 = 1;
+		public int f2 = 2;
+	}
+
+	//====================================================================================================
+	// @BeanProperty.properties annotation on list of beans.
+	//====================================================================================================
+	@Test
+	public void testBeanPropertyProperiesOnListOfBeans() throws Exception {
+		JsonSerializer s = JsonSerializer.DEFAULT_LAX;
+		List<F> l = new LinkedList<F>();
+		F t = new F();
+		t.x1.add(new F());
+		l.add(t);
+		String json = s.serialize(l);
+		assertEquals("[{x1:[{x2:2}],x2:2}]", json);
+	}
+
+	public static class F {
+		@BeanProperty(properties={"x2"}) public List<F> x1 = new LinkedList<F>();
+		public int x2 = 2;
+	}
+
+	//====================================================================================================
+	// Test that URLs and URIs are serialized and parsed correctly.
+	//====================================================================================================
+	@Test
+	public void testURIAttr() throws Exception {
+		JsonSerializer s = JsonSerializer.DEFAULT_LAX;
+		JsonParser p = JsonParser.DEFAULT;
+
+		G t = new G();
+		t.uri = new URI("http://uri");
+		t.f1 = new URI("http://f1");
+		t.f2 = new URL("http://f2");
+
+		String json = s.serialize(t);
+		t = p.parse(json, G.class);
+		assertEquals("http://uri", t.uri.toString());
+		assertEquals("http://f1", t.f1.toString());
+		assertEquals("http://f2", t.f2.toString());
+	}
+
+	public static class G {
+		@BeanProperty(beanUri=true) public URI uri;
+		public URI f1;
+		public URL f2;
+	}
+
+	//====================================================================================================
+	// Test URIs with URI_CONTEXT and URI_AUTHORITY
+	//====================================================================================================
+	@Test
+	public void testUris() throws Exception {
+		WriterSerializer s = new JsonSerializer.Simple();
+		TestURI t = new TestURI();
+		String r;
+		String expected = "";
+
+		s.setProperty(SERIALIZER_relativeUriBase, null);
+		r = s.serialize(t);
+		expected = "{"
+			+"f0:'f0/x0',"
+			+"f1:'f1/x1',"
+			+"f2:'/f2/x2',"
+			+"f3:'http://www.ibm.com/f3/x3',"
+			+"f4:'f4/x4',"
+			+"f5:'/f5/x5',"
+			+"f6:'http://www.ibm.com/f6/x6',"
+			+"f7:'http://www.ibm.com/f7/x7',"
+			+"f8:'f8/x8',"
+			+"f9:'f9/x9',"
+			+"fa:'http://www.ibm.com/fa/xa#MY_LABEL',"
+			+"fb:'http://www.ibm.com/fb/xb?label=MY_LABEL&foo=bar',"
+			+"fc:'http://www.ibm.com/fc/xc?foo=bar&label=MY_LABEL',"
+			+"fd:'http://www.ibm.com/fd/xd?label2=MY_LABEL&foo=bar',"
+			+"fe:'http://www.ibm.com/fe/xe?foo=bar&label2=MY_LABEL'"
+			+"}";
+		assertEquals(expected, r);
+
+		s.setProperty(SERIALIZER_relativeUriBase, "");  // Same as null.
+		r = s.serialize(t);
+		assertEquals(expected, r);
+
+		s.setProperty(SERIALIZER_relativeUriBase, "/cr");
+		r = s.serialize(t);
+		expected = "{"
+			+"f0:'/cr/f0/x0',"
+			+"f1:'/cr/f1/x1',"
+			+"f2:'/f2/x2',"
+			+"f3:'http://www.ibm.com/f3/x3',"
+			+"f4:'/cr/f4/x4',"
+			+"f5:'/f5/x5',"
+			+"f6:'http://www.ibm.com/f6/x6',"
+			+"f7:'http://www.ibm.com/f7/x7',"
+			+"f8:'/cr/f8/x8',"
+			+"f9:'/cr/f9/x9',"
+			+"fa:'http://www.ibm.com/fa/xa#MY_LABEL',"
+			+"fb:'http://www.ibm.com/fb/xb?label=MY_LABEL&foo=bar',"
+			+"fc:'http://www.ibm.com/fc/xc?foo=bar&label=MY_LABEL',"
+			+"fd:'http://www.ibm.com/fd/xd?label2=MY_LABEL&foo=bar',"
+			+"fe:'http://www.ibm.com/fe/xe?foo=bar&label2=MY_LABEL'"
+			+"}";
+		assertEquals(expected, r);
+
+		s.setProperty(SERIALIZER_relativeUriBase, "/cr/");  // Same as above
+		r = s.serialize(t);
+		assertEquals(expected, r);
+
+		s.setProperty(SERIALIZER_relativeUriBase, "/");
+		r = s.serialize(t);
+		expected = "{"
+			+"f0:'/f0/x0',"
+			+"f1:'/f1/x1',"
+			+"f2:'/f2/x2',"
+			+"f3:'http://www.ibm.com/f3/x3',"
+			+"f4:'/f4/x4',"
+			+"f5:'/f5/x5',"
+			+"f6:'http://www.ibm.com/f6/x6',"
+			+"f7:'http://www.ibm.com/f7/x7',"
+			+"f8:'/f8/x8',"
+			+"f9:'/f9/x9',"
+			+"fa:'http://www.ibm.com/fa/xa#MY_LABEL',"
+			+"fb:'http://www.ibm.com/fb/xb?label=MY_LABEL&foo=bar',"
+			+"fc:'http://www.ibm.com/fc/xc?foo=bar&label=MY_LABEL',"
+			+"fd:'http://www.ibm.com/fd/xd?label2=MY_LABEL&foo=bar',"
+			+"fe:'http://www.ibm.com/fe/xe?foo=bar&label2=MY_LABEL'"
+			+"}";
+		assertEquals(expected, r);
+
+		s.setProperty(SERIALIZER_relativeUriBase, null);
+
+		s.setProperty(SERIALIZER_absolutePathUriBase, "http://foo");
+		r = s.serialize(t);
+		expected = "{"
+			+"f0:'f0/x0',"
+			+"f1:'f1/x1',"
+			+"f2:'http://foo/f2/x2',"
+			+"f3:'http://www.ibm.com/f3/x3',"
+			+"f4:'f4/x4',"
+			+"f5:'http://foo/f5/x5',"
+			+"f6:'http://www.ibm.com/f6/x6',"
+			+"f7:'http://www.ibm.com/f7/x7',"
+			+"f8:'f8/x8',"
+			+"f9:'f9/x9',"
+			+"fa:'http://www.ibm.com/fa/xa#MY_LABEL',"
+			+"fb:'http://www.ibm.com/fb/xb?label=MY_LABEL&foo=bar',"
+			+"fc:'http://www.ibm.com/fc/xc?foo=bar&label=MY_LABEL',"
+			+"fd:'http://www.ibm.com/fd/xd?label2=MY_LABEL&foo=bar',"
+			+"fe:'http://www.ibm.com/fe/xe?foo=bar&label2=MY_LABEL'"
+			+"}";
+		assertEquals(expected, r);
+
+		s.setProperty(SERIALIZER_absolutePathUriBase, "http://foo/");
+		r = s.serialize(t);
+		assertEquals(expected, r);
+
+		s.setProperty(SERIALIZER_absolutePathUriBase, "");  // Same as null.
+		r = s.serialize(t);
+		expected = "{"
+			+"f0:'f0/x0',"
+			+"f1:'f1/x1',"
+			+"f2:'/f2/x2',"
+			+"f3:'http://www.ibm.com/f3/x3',"
+			+"f4:'f4/x4',"
+			+"f5:'/f5/x5',"
+			+"f6:'http://www.ibm.com/f6/x6',"
+			+"f7:'http://www.ibm.com/f7/x7',"
+			+"f8:'f8/x8',"
+			+"f9:'f9/x9',"
+			+"fa:'http://www.ibm.com/fa/xa#MY_LABEL',"
+			+"fb:'http://www.ibm.com/fb/xb?label=MY_LABEL&foo=bar',"
+			+"fc:'http://www.ibm.com/fc/xc?foo=bar&label=MY_LABEL',"
+			+"fd:'http://www.ibm.com/fd/xd?label2=MY_LABEL&foo=bar',"
+			+"fe:'http://www.ibm.com/fe/xe?foo=bar&label2=MY_LABEL'"
+			+"}";
+		assertEquals(expected, r);
+	}
+
+	//====================================================================================================
+	// Validate that you cannot update properties on locked serializer.
+	//====================================================================================================
+	@Test
+	public void testLockedSerializer() throws Exception {
+		JsonSerializer s = new JsonSerializer().lock();
+		try {
+			s.setProperty(JsonSerializerContext.JSON_simpleMode, true);
+			fail("Locked exception not thrown");
+		} catch (LockedException e) {}
+		try {
+			s.setProperty(SerializerContext.SERIALIZER_addClassAttrs, true);
+			fail("Locked exception not thrown");
+		} catch (LockedException e) {}
+		try {
+			s.setProperty(BeanContext.BEAN_beanMapPutReturnsOldValue, true);
+			fail("Locked exception not thrown");
+		} catch (LockedException e) {}
+	}
+
+	//====================================================================================================
+	// Recursion
+	//====================================================================================================
+	@Test
+	public void testRecursion() throws Exception {
+		JsonSerializer s = new JsonSerializer.Simple();
+
+		R1 r1 = new R1();
+		R2 r2 = new R2();
+		R3 r3 = new R3();
+		r1.r2 = r2;
+		r2.r3 = r3;
+		r3.r1 = r1;
+
+		// No recursion detection
+		try {
+			s.serialize(r1);
+			fail("Exception expected!");
+		} catch (Exception e) {
+			String msg = e.getLocalizedMessage();
+			assertTrue(msg.contains("It's recommended you use the SerializerContext.SERIALIZER_detectRecursions setting to help locate the loop."));
+		}
+
+		// Recursion detection, no ignore
+		s.setProperty(SERIALIZER_detectRecursions, true);
+		try {
+			s.serialize(r1);
+			fail("Exception expected!");
+		} catch (Exception e) {
+			String msg = e.getLocalizedMessage();
+			assertTrue(msg.contains("[0]root:org.apache.juneau.json.CommonTest$R1"));
+			assertTrue(msg.contains("->[1]r2:org.apache.juneau.json.CommonTest$R2"));
+			assertTrue(msg.contains("->[2]r3:org.apache.juneau.json.CommonTest$R3"));
+			assertTrue(msg.contains("->[3]r1:org.apache.juneau.json.CommonTest$R1"));
+		}
+
+		s.setProperty(SERIALIZER_ignoreRecursions, true);
+		assertEquals("{name:'foo',r2:{name:'bar',r3:{name:'baz'}}}", s.serialize(r1));
+
+		// Make sure this doesn't blow up.
+		s.getSchemaSerializer().serialize(r1);
+	}
+
+	public static class R1 {
+		public String name = "foo";
+		public R2 r2;
+	}
+	public static class R2 {
+		public String name = "bar";
+		public R3 r3;
+	}
+	public static class R3 {
+		public String name = "baz";
+		public R1 r1;
+	}
+
+	//====================================================================================================
+	// Basic bean
+	//====================================================================================================
+	@Test
+	public void testBasicBean() throws Exception {
+		JsonSerializer s = new JsonSerializer.Simple().setProperty(SERIALIZER_trimNullProperties, false).setProperty(BEAN_sortProperties, true);
+
+		J a = new J();
+		a.setF1("J");
+		a.setF2(100);
+		a.setF3(true);
+		assertEquals("C1", "{f1:'J',f2:100,f3:true}", s.serialize(a));
+	}
+
+	public static class J {
+		private String f1 = null;
+		private int f2 = -1;
+		private boolean f3 = false;
+
+		public String getF1() {
+			return this.f1;
+		}
+
+		public void setF1(String f1) {
+			this.f1 = f1;
+		}
+
+		public int getF2() {
+			return this.f2;
+		}
+
+		public void setF2(int f2) {
+			this.f2 = f2;
+		}
+
+		public boolean isF3() {
+			return this.f3;
+		}
+
+		public void setF3(boolean f3) {
+			this.f3 = f3;
+		}
+
+		@Override /* Object */
+		public String toString() {
+			return ("J(f1: " + this.getF1() + ", f2: " + this.getF2() + ")");
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/df0f8689/org.apache.juneau/src/test/java/org/apache/juneau/json/JsonParserTest.java
----------------------------------------------------------------------
diff --git a/org.apache.juneau/src/test/java/org/apache/juneau/json/JsonParserTest.java b/org.apache.juneau/src/test/java/org/apache/juneau/json/JsonParserTest.java
new file mode 100755
index 0000000..1f10dee
--- /dev/null
+++ b/org.apache.juneau/src/test/java/org/apache/juneau/json/JsonParserTest.java
@@ -0,0 +1,331 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations under the License.
+ ***************************************************************************************************************************/
+package org.apache.juneau.json;
+
+import static org.junit.Assert.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.serializer.*;
+import org.junit.*;
+
+@SuppressWarnings("hiding")
+public class JsonParserTest {
+
+	private static final JsonParser p = JsonParser.DEFAULT;
+	private static final JsonParser sp = JsonParser.DEFAULT_STRICT;
+
+
+	//====================================================================================================
+	// Test invalid input
+	//====================================================================================================
+	@Test
+	public void testInvalidJson() {
+		try {
+			p.parse("{\na:1,\nb:xxx\n}", Object.class);
+			fail("Exception expected.");
+		} catch (ParseException e) {}
+	}
+
+	@Test
+	public void testNonExistentAttribute() throws Exception {
+		String json = "{foo:,bar:}";
+		ObjectMap m = p.parse(json, ObjectMap.class);
+		assertEquals("{foo:null,bar:null}", m.toString());
+	}
+
+	@Test
+	public void testNonStringAsString() throws Exception {
+		String json = "123";
+		String s;
+
+		// Strict mode does not allow unquoted values.
+		try {
+			sp.parse(json, String.class);
+			fail("Exception expected");
+		} catch (Exception e) {
+			assertTrue(e.getMessage().contains("Did not find quote character"));
+		}
+
+		s = p.parse(json, String.class);
+		assertEquals("123", s);
+
+		json = " 123 ";
+		// Strict mode does not allow unquoted values.
+		try {
+			sp.parse(json, String.class);
+			fail("Exception expected");
+		} catch (Exception e) {
+			assertTrue(e.getMessage().contains("Did not find quote character"));
+		}
+
+		s = p.parse(json, String.class);
+		assertEquals("123", s);
+
+		json = "{\"fa\":123}";
+		try {
+			sp.parse(json, A.class);
+			fail("Exception expected");
+		} catch (Exception e) {
+			assertTrue(e.getMessage().contains("Did not find quote character"));
+		}
+
+		A a = p.parse(json, A.class);
+		assertEquals("123", a.fa);
+
+		json = " { \"fa\" : 123 } ";
+		try {
+			sp.parse(json, A.class);
+			fail("Exception expected");
+		} catch (Exception e) {
+			assertTrue(e.getMessage().contains("Did not find quote character"));
+		}
+
+		a = p.parse(json, A.class);
+		assertEquals("123", a.fa);
+
+		json = "'123'";
+		try {
+			sp.parse(json, String.class);
+			fail("Exception expected");
+		} catch (Exception e) {
+			assertTrue(e.getMessage().contains("Invalid quote character"));
+		}
+	}
+
+	public static class A {
+		public String fa;
+	}
+
+	@Test
+	public void testCognosJson() throws Exception {
+		String json = TestUtils.readFile(getClass().getResource("/json/BrokenCognosOutput.txt").getPath());
+		p.parse(json, ObjectMap.class);
+	}
+
+	@Test
+	public void testStrictMode() throws Exception {
+		JsonParser p = sp;
+
+		// Missing attribute values.
+		String json = "{\"foo\":,\"bar\":}";
+		try {
+			p.parse(json, ObjectMap.class);
+			fail("Exception expected");
+		} catch (ParseException e) {
+			assertEquals("Parse exception occurred at {currentClass:'Object',line:1,column:7}.  Missing value detected.", e.getRootCause().getMessage());
+		}
+
+		// Single quoted values.
+		json = "{\"foo\":'bar'}";
+		try {
+			p.parse(json, ObjectMap.class);
+			fail("Exception expected");
+		} catch (ParseException e) {
+			assertEquals("Parse exception occurred at {currentClass:'Object',line:1,column:8}.  Invalid quote character \"'\" being used.", e.getRootCause().getMessage());
+		}
+
+		// Single quoted attribute name.
+		json = "{'foo':\"bar\"}";
+		try {
+			p.parse(json, ObjectMap.class);
+			fail("Exception expected");
+		} catch (ParseException e) {
+			assertEquals("Parse exception occurred at {currentClass:'ObjectMap<String,Object>',line:1,column:2}.  Invalid quote character \"'\" being used.", e.getRootCause().getMessage());
+		}
+
+		// Unquoted attribute name.
+		json = "{foo:\"bar\"}";
+		try {
+			p.parse(json, ObjectMap.class);
+			fail("Exception expected");
+		} catch (ParseException e) {
+			assertEquals("Parse exception occurred at {currentClass:'ObjectMap<String,Object>',line:1,column:1}.  Unquoted attribute detected.", e.getRootCause().getMessage());
+		}
+
+		// Concatenated string
+		json = "{\"foo\":\"bar\"+\"baz\"}";
+		try {
+			p.parse(json, ObjectMap.class);
+			fail("Exception expected");
+		} catch (ParseException e) {
+			assertEquals("Parse exception occurred at {currentClass:'Object',line:1,column:12}.  String concatenation detected.", e.getRootCause().getMessage());
+		}
+
+		// Concatenated string 2
+		json = "{\"foo\":\"bar\" + \"baz\"}";
+		try {
+			p.parse(json, ObjectMap.class);
+			fail("Exception expected");
+		} catch (ParseException e) {
+			assertEquals("Parse exception occurred at {currentClass:'Object',line:1,column:13}.  String concatenation detected.", e.getRootCause().getMessage());
+		}
+
+		json = "{\"foo\":/*comment*/\"bar\"}";
+		try {
+			p.parse(json, ObjectMap.class);
+			fail("Exception expected");
+		} catch (ParseException e) {
+			assertEquals("Parse exception occurred at {currentClass:'ObjectMap<String,Object>',line:1,column:8}.  Javascript comment detected.", e.getRootCause().getMessage());
+		}
+	}
+
+	/**
+	 * JSON numbers and booleans should be representable as strings and converted accordingly.
+	 */
+	@Test
+	public void testPrimitivesAsStrings() throws Exception {
+		String json;
+		ReaderParser p = JsonParser.DEFAULT;
+		WriterSerializer s = JsonSerializer.DEFAULT_LAX;
+
+		json = "{f1:'1',f2:'1',f3:'true',f4:'true',f5:'1',f6:'1',f7:'1',f8:'1',f9:'1',f10:'1'}";
+		B b = p.parse(json, B.class);
+		assertEquals("{f1:1,f2:1,f3:true,f4:true,f5:1.0,f6:1.0,f7:1,f8:1,f9:1,f10:1}", s.toString(b));
+
+		json = "{f1:'',f2:'',f3:'',f4:'',f5:'',f6:'',f7:'',f8:'',f9:'',f10:''}";
+		b = p.parse(json, B.class);
+		assertEquals("{f1:0,f2:0,f3:false,f4:false,f5:0.0,f6:0.0,f7:0,f8:0,f9:0,f10:0}", s.toString(b));
+	}
+
+	public static class B {
+		public int f1;
+		public Integer f2;
+		public boolean f3;
+		public Boolean f4;
+		public float f5;
+		public Float f6;
+		public long f7;
+		public Long f8;
+		public byte f9;
+		public Byte f10;
+	}
+
+	//====================================================================================================
+	// testInvalidJsonNumbers
+	// Lax parser allows octal and hexadecimal numbers.  Strict parser does not.
+	//====================================================================================================
+	@Test
+	public void testInvalidJsonNumbers() throws Exception {
+		JsonParser p1 = JsonParser.DEFAULT;
+		JsonParser p2 = JsonParser.DEFAULT_STRICT;
+		Number r;
+
+		// Lax allows blank strings interpreted as 0, strict does not.
+		String s = "\"\"";
+		r = p1.parse(s, Number.class);
+		assertEquals(0, r.intValue());
+		assertTrue(r instanceof Integer);
+		try {
+			r = p2.parse(s, Number.class);
+			fail("Exception expected");
+		} catch (ParseException e) {
+			assertTrue(e.getMessage().endsWith("Invalid JSON number ''"));
+		}
+
+		// Either should allow 0 or -0.
+		s = "0";
+		r = p1.parse(s, Number.class);
+		assertEquals(0, r.intValue());
+		assertTrue(r instanceof Integer);
+		r = p2.parse(s, Number.class);
+		assertEquals(0, r.intValue());
+		assertTrue(r instanceof Integer);
+
+		s = "-0";
+		r = p1.parse(s, Number.class);
+		assertEquals(0, r.intValue());
+		assertTrue(r instanceof Integer);
+		r = p2.parse(s, Number.class);
+		assertEquals(0, r.intValue());
+		assertTrue(r instanceof Integer);
+
+		// Lax allows 0123 and -0123, strict does not.
+		s = "0123";
+		r = p1.parse(s, Number.class);
+		assertEquals(0123, r.intValue());
+		assertTrue(r instanceof Integer);
+		try {
+			r = p2.parse(s, Number.class);
+			fail("Exception expected");
+		} catch (ParseException e) {
+			assertTrue(e.getMessage().endsWith("Invalid JSON number '0123'"));
+		}
+		s = "-0123";
+		r = p1.parse(s, Number.class);
+		assertEquals(-0123, r.intValue());
+		assertTrue(r instanceof Integer);
+		try {
+			r = p2.parse(s, Number.class);
+			fail("Exception expected");
+		} catch (ParseException e) {
+			assertTrue(e.getMessage().endsWith("Invalid JSON number '-0123'"));
+		}
+
+		// Lax allows 0x123 and -0x123, strict does not.
+		s = "0x123";
+		r = p1.parse(s, Number.class);
+		assertEquals(0x123, r.intValue());
+		assertTrue(r instanceof Integer);
+		try {
+			r = p2.parse(s, Number.class);
+			fail("Exception expected");
+		} catch (ParseException e) {
+			assertTrue(e.getMessage().endsWith("Invalid JSON number '0x123'"));
+		}
+		s = "-0x123";
+		r = p1.parse(s, Number.class);
+		assertEquals(-0x123, r.intValue());
+		assertTrue(r instanceof Integer);
+		try {
+			r = p2.parse(s, Number.class);
+			fail("Exception expected");
+		} catch (ParseException e) {
+			assertTrue(e.getMessage().endsWith("Invalid JSON number '-0x123'"));
+		}
+	}
+
+	//====================================================================================================
+	// testUnquotedStrings
+	// Lax parser allows unquoted strings if POJO can be converted from a string.
+	//====================================================================================================
+	@Test
+	public void testUnquotedStrings() throws Exception {
+		JsonParser p1 = JsonParser.DEFAULT;
+		JsonParser p2 = JsonParser.DEFAULT_STRICT;
+
+		String s = "foobar";
+		C c = p1.parse(s, C.class);
+		assertEquals("f=foobar", c.toString());
+
+		try {
+			p2.parse(s, C.class);
+			fail("Exception expected");
+		} catch (ParseException e) {
+			// OK
+		}
+	}
+
+	public static class C {
+		String f;
+		public static C valueOf(String s) {
+			C c = new C();
+			c.f = s;
+			return c;
+		}
+		@Override /* Object */
+		public String toString() {
+			return "f="+f;
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/df0f8689/org.apache.juneau/src/test/java/org/apache/juneau/json/JsonSchemaTest.java
----------------------------------------------------------------------
diff --git a/org.apache.juneau/src/test/java/org/apache/juneau/json/JsonSchemaTest.java b/org.apache.juneau/src/test/java/org/apache/juneau/json/JsonSchemaTest.java
new file mode 100755
index 0000000..f484a07
--- /dev/null
+++ b/org.apache.juneau/src/test/java/org/apache/juneau/json/JsonSchemaTest.java
@@ -0,0 +1,44 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations under the License.
+ ***************************************************************************************************************************/
+package org.apache.juneau.json;
+
+import static org.junit.Assert.*;
+
+import org.junit.*;
+
+public class JsonSchemaTest {
+
+	//====================================================================================================
+	// Primitive objects
+	//====================================================================================================
+	@Test
+	public void testBasic() throws Exception {
+
+		JsonSchemaSerializer s = JsonSerializer.DEFAULT_LAX.getSchemaSerializer();
+
+		Object o = new String();
+		assertEquals("{type:'string',description:'java.lang.String'}", s.serialize(o));
+
+		o = new Integer(123);
+		assertEquals("{type:'number',description:'java.lang.Integer'}", s.serialize(o));
+
+		o = new Float(123);
+		assertEquals("{type:'number',description:'java.lang.Float'}", s.serialize(o));
+
+		o = new Double(123);
+		assertEquals("{type:'number',description:'java.lang.Double'}", s.serialize(o));
+
+		o = Boolean.TRUE;
+		assertEquals("{type:'boolean',description:'java.lang.Boolean'}", s.serialize(o));
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/df0f8689/org.apache.juneau/src/test/java/org/apache/juneau/json/JsonTest.java
----------------------------------------------------------------------
diff --git a/org.apache.juneau/src/test/java/org/apache/juneau/json/JsonTest.java b/org.apache.juneau/src/test/java/org/apache/juneau/json/JsonTest.java
new file mode 100755
index 0000000..6f7fd4f
--- /dev/null
+++ b/org.apache.juneau/src/test/java/org/apache/juneau/json/JsonTest.java
@@ -0,0 +1,308 @@
+/***************************************************************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations under the License.
+ ***************************************************************************************************************************/
+package org.apache.juneau.json;
+
+import static org.apache.juneau.TestUtils.*;
+import static org.apache.juneau.json.JsonSerializerContext.*;
+import static org.apache.juneau.serializer.SerializerContext.*;
+import static org.junit.Assert.*;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.json.annotation.*;
+import org.apache.juneau.serializer.*;
+import org.junit.*;
+
+@SuppressWarnings("serial")
+public class JsonTest {
+
+	//====================================================================================================
+	// testBasic
+	//====================================================================================================
+	@Test
+	public void testBasic() throws Exception {
+		Map<String,Object> m = new LinkedHashMap<String,Object>();
+		List<Object> l = new LinkedList<Object>();
+
+		WriterSerializer s1 = new JsonSerializer.Simple().setProperty(SERIALIZER_trimNullProperties, false);
+		WriterSerializer s2 = new JsonSerializer.Simple().setProperty(SERIALIZER_trimNullProperties, false).setProperty(SERIALIZER_quoteChar, '"');
+		String r;
+
+		// Null keys and values
+		m.clear();
+		m.put(null, null);
+		m.put("aaa", "bbb");
+		assertEquals("A1", "{null:null,aaa:'bbb'}", s1.serialize(m));
+
+		// Escapes.
+		// String = ["]
+		m.clear();
+		m.put("x", "[\"]");
+		assertEquals("{x:\"[\\\"]\"}", s2.serialize(m));
+		// String = [\"]
+		// JSON = {x:"\\\""}
+		m.clear();
+		m.put("x", "[\\\"]");
+		assertEquals("{x:\"[\\\\\\\"]\"}", s2.serialize(m));
+
+		// String = [\w[\w\-\.]{3,}\w]
+		// JSON = {x:"\\w[\\w\\-\\.]{3,}\\w"}
+		m.clear();
+		r = "\\w[\\w\\-\\.]{3,}\\w";
+		m.put("x", r);
+		assertEquals("{x:\"\\\\w[\\\\w\\\\-\\\\.]{3,}\\\\w\"}", s2.serialize(m));
+		assertEquals(r, new ObjectMap(s2.serialize(m)).getString("x"));
+
+		// String = [foo\bar]
+		// JSON = {x:"foo\\bar"}
+		m.clear();
+		m.put("x", "foo\\bar");
+		assertEquals("{x:\"foo\\\\bar\"}", s2.serialize(m));
+
+		m.clear();
+		m.put("null", null);
+		m.put("aaa", "bbb");
+		assertEquals("A2", "{'null':null,aaa:'bbb'}", s1.serialize(m));
+
+		m.clear();
+		m.put(null, "null");
+		m.put("aaa", "bbb");
+		assertEquals("A3", "{null:'null',aaa:'bbb'}", s1.serialize(m));
+
+		// Arrays
+		m.clear();
+		l.clear();
+		m.put("J", "f1");
+		m.put("B", "b");
+		m.put("C", "c");
+		l.add("1");
+		l.add("2");
+		l.add("3");
+		Object o = new Object[] { m, l };
+		Object o2 = new Object[] { o, "foo", "bar", new Integer(1), new Boolean(false), new Float(1.2), null };
+		assertEquals("K1", "[[{J:'f1',B:'b',C:'c'},['1','2','3']],'foo','bar',1,false,1.2,null]", s1.serialize(o2));
+	}
+
+	@Test
+	public void testReservedKeywordAttributes() throws Exception {
+		Map<String,Object> m = new LinkedHashMap<String,Object>();
+
+		// Keys with reserved names.
+		for (String attr : new String[]{"","true","false","null","try","123","1x","-123",".123"}) {
+			m.clear();
+			m.put(attr,1);
+			assertObjectEquals("{'"+attr+"':1}", m);
+		}
+	}
+
+	//====================================================================================================
+	// Validate various backslashes in strings.
+	//====================================================================================================
+	@Test
+	public void testBackslashesInStrings() throws Exception {
+		JsonSerializer s = new JsonSerializer.Simple().setProperty(SERIALIZER_trimNullProperties, false).setProperty(SERIALIZER_quoteChar, '"');
+		String r, r2;
+
+		// [\\]
+		r = "\\";
+		r2 = s.serialize(r);
+		assertEquals(r2, "\"\\\\\"");
+		assertEquals(JsonParser.DEFAULT.parse(r2, Object.class), r);
+
+		// [\b\f\n\t]
+		r = "\b\f\n\t";
+		r2 = s.serialize(r);
+		assertEquals("\"\\b\\f\\n\\t\"", r2);
+		assertEquals(r, JsonParser.DEFAULT.parse(r2, Object.class));
+
+		// Special JSON case:  Forward slashes can OPTIONALLY be escaped.
+		// [\/]
+		assertEquals(JsonParser.DEFAULT.parse("\"\\/\"", Object.class), "/");
+
+		// Unicode
+		r = "\u1234\u1ABC\u1abc";
+		r2 = s.serialize(r);
+		assertEquals("\"\u1234\u1ABC\u1abc\"", r2);
+
+		assertEquals("\u1234", JsonParser.DEFAULT.parse("\"\\u1234\"", Object.class));
+	}
+
+	//====================================================================================================
+	// Indentation
+	//====================================================================================================
+	@Test
+	public void testIndentation() throws Exception {
+		ObjectMap m = new ObjectMap("{J:{B:['c',{D:'e'},['f',{G:'h'},1,false]]},I:'j'}");
+		String e = ""
+			+ "{"
+			+ "\n	J: {"
+			+ "\n		B: ["
+			+ "\n			'c', "
+			+ "\n			{"
+			+ "\n				D: 'e'"
+			+ "\n			}, "
+			+ "\n			["
+			+ "\n				'f', "
+			+ "\n				{"
+			+ "\n					G: 'h'"
+			+ "\n				}, "
+			+ "\n				1, "
+			+ "\n				false"
+			+ "\n			]"
+			+ "\n		]"
+			+ "\n	}, "
+			+ "\n	I: 'j'"
+			+ "\n}";
+		assertEquals(e, JsonSerializer.DEFAULT_LAX_READABLE.serialize(m));
+	}
+
+	//====================================================================================================
+	// Escaping double quotes
+	//====================================================================================================
+	@Test
+	public void testEscapingDoubleQuotes() throws Exception {
+		JsonSerializer s = JsonSerializer.DEFAULT;
+		String r = s.serialize(new ObjectMap().append("f1", "x'x\"x"));
+		assertEquals("{\"f1\":\"x'x\\\"x\"}", r);
+		JsonParser p = JsonParser.DEFAULT;
+		assertEquals("x'x\"x", p.parse(r, ObjectMap.class).getString("f1"));
+	}
+
+	//====================================================================================================
+	// Escaping single quotes
+	//====================================================================================================
+	@Test
+	public void testEscapingSingleQuotes() throws Exception {
+		JsonSerializer s = JsonSerializer.DEFAULT_LAX;
+		String r = s.serialize(new ObjectMap().append("f1", "x'x\"x"));
+		assertEquals("{f1:'x\\'x\"x'}", r);
+		JsonParser p = JsonParser.DEFAULT;
+		assertEquals("x'x\"x", p.parse(r, ObjectMap.class).getString("f1"));
+	}
+
+	//====================================================================================================
+	// testWrapperAttrAnnotationOnBean
+	//====================================================================================================
+	@Test
+	@SuppressWarnings("unchecked")
+	public void testWrapperAttrAnnotationOnBean() throws Exception {
+		JsonSerializer s = JsonSerializer.DEFAULT_LAX;
+		JsonParser p = JsonParser.DEFAULT;
+		String r;
+
+		A t = A.create();
+		r = s.serialize(t);
+		assertEquals("{foo:{f1:1}}", r);
+		t = p.parse(r, A.class);
+		assertEquals(1, t.f1);
+
+		Map<String,A> m = new LinkedHashMap<String,A>();
+		m.put("bar", A.create());
+		r = s.serialize(m);
+		assertEquals("{bar:{foo:{f1:1}}}", r);
+
+		m = p.parseMap(r, LinkedHashMap.class, String.class, A.class);
+		assertEquals(1, m.get("bar").f1);
+	}
+
+	@Json(wrapperAttr="foo")
+	public static class A {
+		public int f1;
+
+		static A create() {
+			A a = new A();
+			a.f1 = 1;
+			return a;
+		}
+	}
+
+	//====================================================================================================
+	// testWrapperAttrAnnotationOnNonBean
+	//====================================================================================================
+	@Test
+	@SuppressWarnings("unchecked")
+	public void testWrapperAttrAnnotationOnNonBean() throws Exception {
+		JsonSerializer s = JsonSerializer.DEFAULT_LAX;
+		JsonParser p = JsonParser.DEFAULT;
+		String r;
+
+		B t = B.create();
+		r = s.serialize(t);
+		assertEquals("{foo:'1'}", r);
+		t = p.parse(r, B.class);
+		assertEquals(1, t.f1);
+
+		Map<String,B> m = new LinkedHashMap<String,B>();
+		m.put("bar", B.create());
+		r = s.serialize(m);
+		assertEquals("{bar:{foo:'1'}}", r);
+
+		m = p.parseMap(r, LinkedHashMap.class, String.class, B.class);
+		assertEquals(1, m.get("bar").f1);
+	}
+
+	@Json(wrapperAttr="foo")
+	public static class B {
+		int f1;
+
+		static B create() {
+			B b = new B();
+			b.f1 = 1;
+			return b;
+		}
+
+		@Override /* Object */
+		public String toString() {
+			return String.valueOf(f1);
+		}
+
+		public static B valueOf(String s) {
+			B b = new B();
+			b.f1 = Integer.parseInt(s);
+			return b;
+		}
+	}
+
+	//====================================================================================================
+	// testAddClassAttrs
+	//====================================================================================================
+	@Test
+	public void testAddClassAttrs() throws Exception {
+		JsonSerializer s = new JsonSerializer().setProperty(SERIALIZER_addClassAttrs, true);
+		Map<String,Object> o = new HashMap<String,Object>();
+		o.put("c", new C());
+		assertEquals("{\"c\":{\"_class\":\"org.apache.juneau.json.JsonTest$C\",\"items\":[]}}", s.serialize(o));
+	}
+
+	public static class C extends LinkedList<String> {
+	}
+
+	//====================================================================================================
+	// testEscapeSolidus
+	//====================================================================================================
+	@Test
+	public void testEscapeSolidus() throws Exception {
+		JsonSerializer s = new JsonSerializer().setProperty(JSON_escapeSolidus, false);
+		String r = s.serialize("foo/bar");
+		assertEquals("\"foo/bar\"", r);
+		r = JsonParser.DEFAULT.parse(r, String.class);
+		assertEquals("foo/bar", r);
+
+		s = new JsonSerializer().setProperty(JSON_escapeSolidus, true);
+		r = s.serialize("foo/bar");
+		assertEquals("\"foo\\/bar\"", r);
+		r = JsonParser.DEFAULT.parse(r, String.class);
+		assertEquals("foo/bar", r);
+	}
+}
\ No newline at end of file