/* * Copyright (c) 2008-2014 MongoDB, Inc. * * Licensed 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 com.mongodb.util; import com.mongodb.BasicDBObject; import com.mongodb.BasicDBObjectBuilder; import com.mongodb.DBObject; import org.bson.BSON; import org.bson.BasicBSONObject; import org.bson.types.BSONTimestamp; import org.bson.types.Code; import org.bson.types.CodeWScope; import org.bson.types.ObjectId; import org.junit.Test; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.GregorianCalendar; import java.util.SimpleTimeZone; import java.util.UUID; import java.util.regex.Pattern; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @SuppressWarnings("deprecation") public class JSONTest { @Test public void testSerializationMethods() { // basic test of each of JSON class' serialization methods String json = "{ \"x\" : \"basic test\"}"; Object obj = JSON.parse(json); assertEquals(json, JSON.serialize(obj)); } @Test public void testNumbers() { assertEquals("{ \"x\" : 5}", JSON.serialize(JSON.parse("{'x' : 5 }"))); assertEquals("{ \"x\" : 5.0}", JSON.serialize(JSON.parse("{'x' : 5.0 }"))); assertEquals("{ \"x\" : 0}", JSON.serialize(JSON.parse("{'x' : 0 }"))); assertEquals("{ \"x\" : 0.0}", JSON.serialize(JSON.parse("{'x' : 0.0 }"))); assertEquals("{ \"x\" : 500}", JSON.serialize(JSON.parse("{'x' : 500 }"))); assertEquals("{ \"x\" : 500.0}", JSON.serialize(JSON.parse("{'x' : 500.0 }"))); assertEquals("{ \"x\" : 0.5}", JSON.serialize(JSON.parse("{'x' : 0.500 }"))); assertEquals("{ \"x\" : 5.0}", JSON.serialize(JSON.parse("{'x' : 5. }"))); assertEquals("{ \"x\" : 50.0}", JSON.serialize(JSON.parse("{'x' : 5.0e+1 }"))); assertEquals("{ \"x\" : 0.5}", JSON.serialize(JSON.parse("{'x' : 5.0E-1 }"))); } @Test public void testLongValues() { Long bigVal = Integer.MAX_VALUE + 1L; String test = String.format("{ \"x\" : %d}", bigVal); assertEquals(test, JSON.serialize(JSON.parse(test))); Long smallVal = Integer.MIN_VALUE - 1L; String test2 = String.format("{ \"x\" : %d}", smallVal); assertEquals(test2, JSON.serialize(JSON.parse(test2))); try { JSON.parse("{\"ReallyBigNumber\": 10000000000000000000 }"); fail("JSONParseException should have been thrown"); } catch (JSONParseException e) { // fall through } } @Test public void testSimple() { assertEquals("{ \"csdf\" : true}", JSON.serialize(JSON.parse("{'csdf' : true}"))); assertEquals("{ \"csdf\" : false}", JSON.serialize(JSON.parse("{'csdf' : false}"))); assertEquals("{ \"csdf\" : null }", JSON.serialize(JSON.parse("{'csdf' : null}"))); assertEquals("{ \"id\" : \"1689c12eb234c54a84ebd100\"}", JSON.serialize(JSON.parse("{\n\t\"id\":\"1689c12eb234c54a84ebd100\",\n}"))); } @Test public void testString() { assertEquals("{ \"csdf\" : \"foo\"}", JSON.serialize(JSON.parse("{'csdf' : \"foo\"}"))); assertEquals("{ \"csdf\" : \"foo\"}", JSON.serialize(JSON.parse("{'csdf' : \'foo\'}"))); assertEquals("{ \"csdf\" : \"a\\\"b\"}", JSON.serialize(JSON.parse("{'csdf' : \"a\\\"b\"}"))); } @Test public void testArray() { assertEquals("{ \"csdf\" : [ \"foo\"]}", JSON.serialize(JSON.parse("{'csdf' : [\"foo\"]}"))); assertEquals("{ \"csdf\" : [ 3 , 5 , \"foo\" , null ]}", JSON.serialize(JSON.parse("{'csdf' : [3, 5, \'foo\', null]}"))); assertEquals("{ \"csdf\" : [ 3.0 , 5.0 , \"foo\" , null ]}", JSON.serialize(JSON.parse("{'csdf' : [3.0, 5.0, \'foo\', null]}"))); assertEquals("{ \"csdf\" : [ [ ] , [ [ ]] , false]}", JSON.serialize(JSON.parse("{'csdf' : [[],[[]],false]}"))); } @Test public void testObject() { assertEquals("{ \"csdf\" : { }}", JSON.serialize(JSON.parse("{'csdf' : {}}"))); assertEquals("{ \"csdf\" : { \"foo\" : \"bar\"}}", JSON.serialize(JSON.parse("{'csdf' : {\"foo\":\"bar\"}}"))); assertEquals("{ \"csdf\" : { \"hi\" : { \"hi\" : [ { }]}}}", JSON.serialize(JSON.parse("{'csdf' : {\'hi\':{\'hi\':[{}]}}}"))); } @Test public void testMulti() { assertEquals("{ \"\" : \"\" , \"34\" : -52.5}", JSON.serialize(JSON.parse("{\'\' : \"\", \"34\" : -52.5}"))); } @Test public void testUnicode() { assertEquals("{ \"x\" : \"hi \"}", JSON.serialize(JSON.parse("{'x' : \"hi\\u0020\"}"))); assertEquals("{ \"x\" : \"\u0E01\u2702\uF900\"}", JSON.serialize(JSON.parse("{ \"x\" : \"\\u0E01\\u2702\\uF900\"}"))); assertEquals("{ \"x\" : \"foo bar\"}", JSON.serialize(JSON.parse("{ \"x\" : \"foo\\u0020bar\"}"))); } @Test public void testBin() { byte[] b = {'a', 'b', 0, 'd'}; DBObject obj = BasicDBObjectBuilder.start().add("b", b).get(); assertEquals("{ \"b\" : <Binary Data>}", JSON.serialize(obj)); } @Test public void testErrors() { boolean threw = false; try { JSON.parse("{\"x\" : \""); } catch (JSONParseException e) { threw = true; } assertEquals(true, threw); threw = false; try { JSON.parse("{\"x\" : \"\\"); } catch (JSONParseException e) { threw = true; } assertEquals(true, threw); threw = false; try { JSON.parse("{\"x\" : 5.2"); } catch (JSONParseException e) { threw = true; } assertEquals(true, threw); threw = false; try { JSON.parse("{\"x\" : 5"); } catch (JSONParseException e) { threw = true; } assertEquals(true, threw); threw = false; try { JSON.parse("{\"x\" : 5,"); } catch (JSONParseException e) { threw = true; } assertEquals(true, threw); threw = false; } @Test public void testBasic() { assertEquals("{ }", JSON.serialize(JSON.parse("{}"))); assertEquals(null, JSON.parse("")); assertEquals(null, JSON.parse(" ")); assertEquals(null, JSON.parse(null)); boolean threw = false; try { JSON.parse("{"); } catch (JSONParseException e) { threw = true; } assertEquals(true, threw); threw = false; try { JSON.parse("}"); } catch (JSONParseException e) { threw = true; } assertEquals(true, threw); threw = false; try { JSON.parse("{{}"); } catch (JSONParseException e) { threw = true; } assertEquals(true, threw); threw = false; try { JSON.parse("4"); } catch (JSONParseException e) { threw = true; } assertEquals(false, threw); threw = false; assertEquals(JSON.parse("4"), 4); } @Test public void testNumbers2() { DBObject x = new BasicDBObject("x", 123); assertEquals(JSON.parse(x.toString()), x); x = new BasicDBObject("x", 123123123123L); assertEquals(JSON.parse(x.toString()), x); x = new BasicDBObject("x", 123123123); assertEquals(JSON.parse(x.toString()), x); } private void escapeChar(final String s) { String thingy = "va" + s + "lue"; DBObject x = new BasicDBObject("name", thingy); x = (DBObject) JSON.parse(x.toString()); assertEquals(x.get("name"), thingy); thingy = "va" + s + s + s + "lue" + s; x = new BasicDBObject("name", thingy); x = (DBObject) JSON.parse(x.toString()); assertEquals(x.get("name"), thingy); } @Test public void testEscape1() { String raw = "a\nb"; DBObject x = new BasicDBObject("x", raw); assertEquals("\"a\\nb\"", JSON.serialize(raw)); assertEquals(x, JSON.parse(x.toString())); assertEquals(raw, ((DBObject) JSON.parse(x.toString())).get("x")); x = new BasicDBObject("x", "a\nb\bc\td\re"); assertEquals(x, JSON.parse(x.toString())); String thingy = "va\"lue"; x = new BasicDBObject("name", thingy); x = (DBObject) JSON.parse(x.toString()); assertEquals(thingy, x.get("name")); thingy = "va\\lue"; x = new BasicDBObject("name", thingy); x = (DBObject) JSON.parse(x.toString()); assertEquals(thingy, x.get("name")); assertEquals("va/lue", JSON.parse("\"va\\/lue\"")); assertEquals("value", JSON.parse("\"va\\lue\"")); assertEquals("va\\lue", JSON.parse("\"va\\\\lue\"")); escapeChar("\t"); escapeChar("\b"); escapeChar("\n"); escapeChar("\r"); escapeChar("\'"); escapeChar("\""); escapeChar("\\"); } // This is not correct behavior, but adding the test here to document it. It should probably throw a JSONParseException due to the // illegal escape of \m. @Test public void testIllegalEscape() { DBObject obj = (DBObject) JSON.parse("{ 'x' : '\\m' }"); assertEquals("m", obj.get("x")); } @Test public void testPattern() { String x = "^Hello$"; String serializedPattern = "{ \"$regex\" : \"" + x + "\" , \"$options\" : \"" + "i\"}"; Pattern pattern = Pattern.compile(x, Pattern.CASE_INSENSITIVE); assertEquals(serializedPattern, JSON.serialize(pattern)); BasicDBObject a = new BasicDBObject("x", pattern); assertEquals("{ \"x\" : " + serializedPattern + "}", a.toString()); DBObject b = (DBObject) JSON.parse(a.toString()); assertEquals(Pattern.class, b.get("x").getClass()); assertEquals(b.toString(), a.toString()); } @Test public void testRegexNoOptions() { String x = "^Hello$"; String serializedPattern = "{ \"$regex\" : \"" + x + "\"}"; Pattern pattern = Pattern.compile(x); assertEquals(JSON.serialize(pattern), serializedPattern); BasicDBObject a = new BasicDBObject("x", pattern); assertEquals(a.toString(), "{ \"x\" : " + serializedPattern + "}"); DBObject b = (DBObject) JSON.parse(a.toString()); assertEquals(Pattern.class, b.get("x").getClass()); assertEquals(b.toString(), a.toString()); } @Test public void testObjectId() { ObjectId oid = new ObjectId(new Date()); String serialized = JSON.serialize(oid); assertEquals("{ \"$oid\" : \"" + oid + "\"}", serialized); ObjectId oid2 = (ObjectId) JSON.parse(serialized); assertEquals(oid, oid2); } @Test public void testDate() { Date d = new Date(); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); format.setCalendar(new GregorianCalendar(new SimpleTimeZone(0, "GMT"))); String formattedDate = format.format(d); String serialized = JSON.serialize(d); assertEquals("{ \"$date\" : \"" + formattedDate + "\"}", serialized); Date d2 = (Date) JSON.parse(serialized); assertEquals(d2.toString(), d.toString()); assertTrue(d.equals(d2)); } @Test public void testJSONEncoding() throws ParseException { String json = "{ 'str' : 'asdfasd' , 'long' : 123123123123 , 'int' : 5 , 'float' : 0.4 , 'bool' : false , " + "'date' : { '$date' : '2011-05-18T18:56:00Z'} , 'pat' : { '$regex' : '.*' , '$options' : ''} , " + "'oid' : { '$oid' : '4d83ab3ea39562db9c1ae2ae'} , 'ref' : { '$ref' : 'test.test' , " + "'$id' : { '$oid' : '4d83ab59a39562db9c1ae2af'}} , 'code' : { '$code' : 'asdfdsa'} , " + "'codews' : { '$code' : 'ggggg' , " + "'$scope' : { }} , 'ts' : { '$ts' : 1300474885 , '$inc' : 10} , 'null' : null, " + "'uuid' : { '$uuid' : '60f65152-6d4a-4f11-9c9b-590b575da7b5' }}"; BasicDBObject a = (BasicDBObject) JSON.parse(json); assertEquals("asdfasd", a.get("str")); assertEquals(5, a.get("int")); assertEquals(123123123123L, a.get("long")); assertEquals(0.4d, a.get("float")); assertEquals(false, a.get("bool")); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); format.setCalendar(new GregorianCalendar(new SimpleTimeZone(0, "GMT"))); assertEquals(format.parse("2011-05-18T18:56:00Z"), a.get("date")); Pattern pat = (Pattern) a.get("pat"); Pattern pat2 = Pattern.compile(".*", BSON.regexFlags("")); assertEquals(pat.pattern(), pat2.pattern()); assertEquals(pat.flags(), pat2.flags()); ObjectId oid = (ObjectId) a.get("oid"); assertEquals(new ObjectId("4d83ab3ea39562db9c1ae2ae"), oid); // DBRef ref = (DBRef) a.get("ref"); // assertEquals(new DBRef(null, "test.test", new ObjectId("4d83ab59a39562db9c1ae2af")), ref); assertEquals(new Code("asdfdsa"), a.get("code")); assertEquals(new CodeWScope("ggggg", new BasicBSONObject()), a.get("codews")); assertEquals(new BSONTimestamp(1300474885, 10), a.get("ts")); assertEquals(UUID.fromString("60f65152-6d4a-4f11-9c9b-590b575da7b5"), a.get("uuid")); String json2 = JSON.serialize(a); BasicDBObject b = (BasicDBObject) JSON.parse(json2); assertEquals(JSON.serialize(b), JSON.serialize(b)); } }