Skip to content

Commit 2ead653

Browse files
committed
support any
1 parent 3ffc270 commit 2ead653

File tree

11 files changed

+306
-19
lines changed

11 files changed

+306
-19
lines changed

src/main/java/com/jsoniter/Any.java

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
package com.jsoniter;
2+
3+
import java.lang.reflect.Array;
4+
import java.util.Collection;
5+
import java.util.List;
6+
import java.util.Map;
7+
8+
public class Any {
9+
10+
private final Object val;
11+
public Object lastAccessed;
12+
13+
public Any(Object val) {
14+
this.val = val;
15+
}
16+
17+
public ValueType getValueType(Object... keys) {
18+
try {
19+
lastAccessed = getPath(val, keys);
20+
if (lastAccessed == null) {
21+
return ValueType.NULL;
22+
}
23+
Class<?> clazz = lastAccessed.getClass();
24+
if (clazz == String.class) {
25+
return ValueType.STRING;
26+
}
27+
if (clazz.isArray()) {
28+
return ValueType.ARRAY;
29+
}
30+
if (lastAccessed instanceof Number) {
31+
return ValueType.NUMBER;
32+
}
33+
if (lastAccessed instanceof List) {
34+
return ValueType.ARRAY;
35+
}
36+
return ValueType.OBJECT;
37+
} catch (ClassCastException e) {
38+
return ValueType.INVALID;
39+
} catch (IndexOutOfBoundsException e) {
40+
return ValueType.INVALID;
41+
}
42+
}
43+
44+
public Object get(Object... keys) {
45+
try {
46+
return lastAccessed = getPath(val, keys);
47+
} catch (ClassCastException e) {
48+
return null;
49+
} catch (IndexOutOfBoundsException e) {
50+
return null;
51+
}
52+
}
53+
54+
public boolean exists(Object... keys) {
55+
try {
56+
lastAccessed = getPath(val, keys);
57+
return true;
58+
} catch (ClassCastException e) {
59+
return false;
60+
} catch (IndexOutOfBoundsException e) {
61+
return false;
62+
}
63+
}
64+
65+
public String toString() {
66+
return toString(new Object[0]);
67+
}
68+
69+
public String toString(Object... keys) {
70+
get(keys);
71+
if (lastAccessed == null) {
72+
return "null";
73+
}
74+
return lastAccessed.toString();
75+
}
76+
77+
@Override
78+
public boolean equals(Object o) {
79+
if (this == o) return true;
80+
if (o == null || getClass() != o.getClass()) return false;
81+
82+
Any any = (Any) o;
83+
84+
return val != null ? val.equals(any.val) : any.val == null;
85+
86+
}
87+
88+
@Override
89+
public int hashCode() {
90+
return val != null ? val.hashCode() : 0;
91+
}
92+
93+
public int toInt(Object... keys) {
94+
get(keys);
95+
if (lastAccessed == null) {
96+
return 0;
97+
}
98+
if (lastAccessed.getClass() == String.class) {
99+
return Integer.valueOf((String) lastAccessed);
100+
}
101+
Number number = (Number) lastAccessed;
102+
return number.intValue();
103+
}
104+
105+
public short toShort(Object... keys) {
106+
get(keys);
107+
if (lastAccessed == null) {
108+
return 0;
109+
}
110+
if (lastAccessed.getClass() == String.class) {
111+
return Short.valueOf((String) lastAccessed);
112+
}
113+
Number number = (Number) lastAccessed;
114+
return number.shortValue();
115+
}
116+
117+
public long toLong(Object... keys) {
118+
get(keys);
119+
if (lastAccessed == null) {
120+
return 0;
121+
}
122+
if (lastAccessed.getClass() == String.class) {
123+
return Long.valueOf((String) lastAccessed);
124+
}
125+
Number number = (Number) lastAccessed;
126+
return number.longValue();
127+
}
128+
129+
public float toFloat(Object... keys) {
130+
get(keys);
131+
if (lastAccessed == null) {
132+
return 0;
133+
}
134+
if (lastAccessed.getClass() == String.class) {
135+
return Float.valueOf((String) lastAccessed);
136+
}
137+
Number number = (Number) lastAccessed;
138+
return number.floatValue();
139+
}
140+
141+
public double toDouble(Object... keys) {
142+
get(keys);
143+
if (lastAccessed == null) {
144+
return 0;
145+
}
146+
if (lastAccessed.getClass() == String.class) {
147+
return Double.valueOf((String) lastAccessed);
148+
}
149+
Number number = (Number) lastAccessed;
150+
return number.doubleValue();
151+
}
152+
153+
public boolean toBoolean(Object... keys) {
154+
get(keys);
155+
if (lastAccessed == null) {
156+
return false;
157+
}
158+
if (lastAccessed instanceof Number) {
159+
Number number = (Number) lastAccessed;
160+
return number.intValue() != 0;
161+
}
162+
if (lastAccessed.getClass().isArray()) {
163+
return Array.getLength(lastAccessed) != 0;
164+
}
165+
if (lastAccessed instanceof Collection) {
166+
Collection col = (Collection) lastAccessed;
167+
return col.size() != 0;
168+
}
169+
if (lastAccessed instanceof Map) {
170+
Map map = (Map) lastAccessed;
171+
return map.size() != 0;
172+
}
173+
return true;
174+
}
175+
176+
private static Object getPath(Object val, Object... keys) {
177+
if (keys.length == 0) {
178+
return val;
179+
}
180+
Object key = keys[0];
181+
if (key instanceof Integer) {
182+
Object nextVal = getFromArrayOrList(val, (Integer)key);
183+
Object[] nextKeys = new Object[keys.length - 1];
184+
System.arraycopy(keys, 1, nextKeys, 0, nextKeys.length);
185+
return getPath(nextVal, nextKeys);
186+
}
187+
if (key instanceof String) {
188+
Object nextVal = getFromMap(val, (String)key);
189+
Object[] nextKeys = new Object[keys.length - 1];
190+
System.arraycopy(keys, 1, nextKeys, 0, nextKeys.length);
191+
return getPath(nextVal, nextKeys);
192+
}
193+
throw new RuntimeException("invalid key type: " + key);
194+
}
195+
196+
private static Object getFromMap(Object val, String key) {
197+
Map map = (Map) val;
198+
return map.get(key);
199+
}
200+
201+
private static Object getFromArrayOrList(Object val, Integer key) {
202+
if (val.getClass().isArray()) {
203+
return Array.get(val, key);
204+
}
205+
List list = (List) val;
206+
return list.get(key);
207+
}
208+
}

src/main/java/com/jsoniter/Codegen.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ class Codegen {
2727
put(Integer.class.getName(), "Integer.valueOf(iter.readInt())");
2828
put(Long.class.getName(), "Long.valueOf(iter.readLong())");
2929
put(String.class.getName(), "iter.readString()");
30-
put(Object.class.getName(), "iter.readAny()");
30+
put(Object.class.getName(), "iter.readAnyObject()");
31+
put(Any.class.getName(), "iter.readAny()");
3132
}};
3233
final static Set<Class> WITH_CAPACITY_COLLECTION_CLASSES = new HashSet<Class>() {{
3334
add(ArrayList.class);

src/main/java/com/jsoniter/Jsoniter.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -663,7 +663,11 @@ public final double readDouble() throws IOException {
663663
return Double.valueOf(readNumber());
664664
}
665665

666-
public final Object readAny() throws IOException {
666+
public final Any readAny() throws IOException {
667+
return new Any(readAnyObject());
668+
}
669+
670+
public final Object readAnyObject() throws IOException {
667671
ValueType valueType = whatIsNext();
668672
switch (valueType) {
669673
case STRING:
@@ -677,17 +681,17 @@ public final Object readAny() throws IOException {
677681
case ARRAY:
678682
ArrayList list = new ArrayList();
679683
while (readArray()) {
680-
list.add(readAny());
684+
list.add(readAnyObject());
681685
}
682686
return list;
683687
case OBJECT:
684688
Map map = new HashMap();
685689
for (String field = readObject(); field != null; field = readObject()) {
686-
map.put(field, readObject());
690+
map.put(field, readAnyObject());
687691
}
688692
return map;
689693
default:
690-
throw reportError("readAny", "unexpected value type: " + valueType);
694+
throw reportError("readAnyObject", "unexpected value type: " + valueType);
691695
}
692696
}
693697

src/main/java/com/jsoniter/Slice.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.jsoniter;
22

3-
class Slice {
3+
public class Slice {
44

55
public byte[] data;
66
public int head;

test/main/java/com/jsoniter/ComplexObject.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@
55
public class ComplexObject {
66
public int field1;
77
public List<Integer> field2;
8+
public Any field3;
89
}

test/main/java/com/jsoniter/MyObject.java

Lines changed: 0 additions & 5 deletions
This file was deleted.
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.jsoniter;
2+
3+
import junit.framework.TestCase;
4+
5+
import java.util.ArrayList;
6+
import java.util.HashMap;
7+
8+
public class TestAny extends TestCase {
9+
public void test_get() {
10+
assertEquals("hello", new Any("hello").get());
11+
assertEquals("hello", new Any(new String[]{"hello"}).get(0));
12+
assertNull(new Any(new String[]{"hello"}).get(1));
13+
assertNull(new Any(new String[]{"hello"}).get(-1));
14+
assertFalse(new Any(new String[]{"hello"}).exists(-1));
15+
assertEquals("hello", new Any(new ArrayList(){{
16+
add("hello");
17+
}}).get(0));
18+
assertNull(new Any(new ArrayList(){{
19+
add("hello");
20+
}}).get(2));
21+
assertEquals("world", new Any(new HashMap(){{
22+
put("hello", "world");
23+
}}).get("hello"));
24+
assertNull(new Any(new HashMap(){{
25+
put("hello", "world");
26+
}}).get(1));
27+
assertNull(new Any(new HashMap(){{
28+
put("hello", "world");
29+
}}).get("abc"));
30+
assertEquals("2", new Any(new HashMap(){{
31+
put("hello", new String[]{"1", "2"});
32+
}}).get("hello", 1));
33+
}
34+
35+
public void test_get_value_type() {
36+
assertEquals(ValueType.STRING, new Any("hello").getValueType());
37+
assertEquals(ValueType.NULL, new Any(null).getValueType());
38+
assertEquals(ValueType.NUMBER, new Any(1.1).getValueType());
39+
assertEquals(ValueType.ARRAY, new Any(new String[0]).getValueType());
40+
assertEquals(ValueType.ARRAY, new Any(new ArrayList()).getValueType());
41+
assertEquals(ValueType.OBJECT, new Any(new SimpleObject()).getValueType());
42+
}
43+
44+
public void test_to_string() {
45+
assertEquals("hello", new Any("hello").toString());
46+
assertEquals("null", new Any(null).toString());
47+
}
48+
49+
public void test_equals() {
50+
assertEquals(new Any("hello"), new Any("hello"));
51+
}
52+
53+
public void test_to_int() {
54+
assertEquals(123, new Any("123").toInt());
55+
assertEquals(123, new Any(123.3).toInt());
56+
}
57+
58+
public void test_to_boolean() {
59+
assertTrue(new Any("123").toBoolean());
60+
}
61+
}

test/main/java/com/jsoniter/TestCustomize.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,16 @@ public Object decode(Type type, Jsoniter iter) throws IOException {
2121
}
2222

2323
public void test_customize_field() throws IOException {
24-
Jsoniter.registerFieldDecoder(MyObject.class, "field1", new Decoder(){
24+
Jsoniter.registerFieldDecoder(SimpleObject.class, "field1", new Decoder(){
2525

2626
@Override
2727
public Object decode(Type type, Jsoniter iter) throws IOException {
2828
return Integer.toString(iter.readInt());
2929
}
3030
});
3131
Jsoniter iter = Jsoniter.parse("{'field1': 100}".replace('\'', '"'));
32-
MyObject myObject = iter.read(MyObject.class);
32+
SimpleObject myObject = iter.read(SimpleObject.class);
3333
assertEquals("100", myObject.field1);
34+
Jsoniter.clearDecoders();
3435
}
3536
}

test/main/java/com/jsoniter/TestDemo.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public void test_bind_api() throws IOException {
1212
}
1313
public void test_any_api() throws IOException {
1414
Jsoniter iter = Jsoniter.parse("[0,1,2,3]");
15-
Object val = iter.readAny();
15+
System.out.println(iter.readAny().toInt(3));
1616
}
1717
public void test_iterator_api() throws IOException {
1818
Jsoniter iter = Jsoniter.parse("[0,1,2,3]");
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.jsoniter;
2+
3+
import junit.framework.TestCase;
4+
5+
import java.io.IOException;
6+
7+
public class TestReadAny extends TestCase {
8+
public void test_read_any() throws IOException {
9+
Jsoniter iter = Jsoniter.parse("[0,1,2,3]");
10+
assertEquals(3, iter.readAny().toInt(3));
11+
}
12+
public void test_bind_to_any() throws IOException {
13+
Jsoniter iter = Jsoniter.parse("{'field3': 100}".replace('\'', '"'));
14+
ComplexObject obj = iter.read(ComplexObject.class);
15+
System.out.println(obj.field3);
16+
}
17+
}

0 commit comments

Comments
 (0)