blob: b7ee759ebb61a69d83568cbcd4f7ad877b7b2dad [file] [log] [blame]
// ***************************************************************************************************************************
// * 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.TestUtils.*;
import static org.junit.Assert.*;
import java.io.*;
import org.apache.juneau.*;
import org.apache.juneau.parser.*;
import org.apache.juneau.serializer.*;
import org.junit.*;
@SuppressWarnings({})
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 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) {
assertTrue(e.getRootCause().getMessage().contains("Missing value detected."));
}
// Single quoted values.
json = "{\"foo\":'bar'}";
try {
p.parse(json, ObjectMap.class);
fail("Exception expected");
} catch (ParseException e) {
assertTrue(e.getRootCause().getMessage().contains("Invalid quote character"));
}
// Single quoted attribute name.
json = "{'foo':\"bar\"}";
try {
p.parse(json, ObjectMap.class);
fail("Exception expected");
} catch (ParseException e) {
assertTrue(e.getRootCause().getMessage().contains("Invalid quote character"));
}
// Unquoted attribute name.
json = "{foo:\"bar\"}";
try {
p.parse(json, ObjectMap.class);
fail("Exception expected");
} catch (ParseException e) {
assertTrue(e.getRootCause().getMessage().contains("Unquoted attribute detected."));
}
// Concatenated string
json = "{\"foo\":\"bar\"+\"baz\"}";
try {
p.parse(json, ObjectMap.class);
fail("Exception expected");
} catch (ParseException e) {
assertTrue(e.getRootCause().getMessage().contains("String concatenation detected."));
}
// Concatenated string 2
json = "{\"foo\":\"bar\" + \"baz\"}";
try {
p.parse(json, ObjectMap.class);
fail("Exception expected");
} catch (ParseException e) {
assertTrue(e.getRootCause().getMessage().contains("String concatenation detected."));
}
json = "{\"foo\":/*comment*/\"bar\"}";
try {
p.parse(json, ObjectMap.class);
fail("Exception expected");
} catch (ParseException e) {
assertTrue(e.getRootCause().getMessage().contains("Javascript comment detected."));
}
}
/**
* 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 = SimpleJsonSerializer.DEFAULT;
json = "{f01:'1',f02:'1',f03:'true',f04:'true',f05:'1',f06:'1',f07:'1',f08:'1',f09:'1',f10:'1'}";
B b = p.parse(json, B.class);
assertEquals("{f01:1,f02:1,f03:true,f04:true,f05:1.0,f06:1.0,f07:1,f08:1,f09:1,f10:1}", s.toString(b));
json = "{f01:'',f02:'',f03:'',f04:'',f05:'',f06:'',f07:'',f08:'',f09:'',f10:''}";
b = p.parse(json, B.class);
assertEquals("{f01:0,f02:0,f03:false,f04:false,f05:0.0,f06:0.0,f07:0,f08:0,f09:0,f10:0}", s.toString(b));
}
public static class B {
public int f01;
public Integer f02;
public boolean f03;
public Boolean f04;
public float f05;
public Float f06;
public long f07;
public Long f08;
public byte f09;
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().contains("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().contains("Invalid JSON number"));
}
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().contains("Invalid JSON number"));
}
// 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().contains("Invalid JSON number"));
}
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().contains("Invalid JSON number"));
}
}
//====================================================================================================
// 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;
}
}
//====================================================================================================
// testStreamsAutoClose
// Validates PARSER_autoCloseStreams.
//====================================================================================================
@Test
public void testStreamsAutoClose() throws Exception {
ReaderParser p = JsonParser.DEFAULT.builder().autoCloseStreams().build();
Object x;
Reader r;
r = reader("{foo:'bar'}{baz:'qux'}");
x = p.parse(r, ObjectMap.class);
assertObjectEquals("{foo:'bar'}", x);
try {
x = p.parse(r, ObjectMap.class);
fail("Exception expected");
} catch (Exception e) {
assertTrue(e.getMessage().contains("Reader is closed"));
}
}
//====================================================================================================
// testMultipleObjectsInStream
// Validates that readers are not closed so that we can read streams of POJOs.
//====================================================================================================
@Test
public void testMultipleObjectsInStream() throws Exception {
ReaderParser p = JsonParser.create().unbuffered().build();
Object x;
Reader r;
r = reader("{foo:'bar'}{baz:'qux'}");
x = p.parse(r, ObjectMap.class);
assertObjectEquals("{foo:'bar'}", x);
x = p.parse(r, ObjectMap.class);
assertObjectEquals("{baz:'qux'}", x);
r = reader("[123][456]");
x = p.parse(r, ObjectList.class);
assertObjectEquals("[123]", x);
x = p.parse(r, ObjectList.class);
assertObjectEquals("[456]", x);
}
private Reader reader(String in) {
return new CloseableStringReader(in);
}
}