Skip to content

Commit 1754bf9

Browse files
committed
2.0.0 draft
1 parent 7a829e0 commit 1754bf9

File tree

6 files changed

+77
-31
lines changed

6 files changed

+77
-31
lines changed

README

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Overview:
2929
- after JSON text parsing or normalization, they are stored as:
3030
BigDecimal, Object[] {BigDecimal,...}, Object[] {String,...}
3131

32-
Constructor:
32+
Constructors:
3333
JSON(String jsonText) throws IOException, ParseException;
3434
JSON(Reader reader) throws IOException, ParseException;
3535
JSON(Object... members) throws IndexOutOfBoundsException; // name,value pairs
@@ -70,6 +70,7 @@ Overview:
7070
- casting null to a Java primitive returns corresponding initial value;
7171
- casting null to an array returns an empty array;
7272
- casting null to String returns "null";
73+
- casting null to other Java objects returns null;
7374
- casting to null returns null.
7475

7576
static <T> T cast(Object jsonVal, T sample);
@@ -78,10 +79,10 @@ Overview:
7879

7980
Abstract class JSONObject;
8081

81-
Converts Java object fields to/from JSON object.
82+
Unloads/loads Java object accessible fields to/from JSON object.
83+
- Java final, interface, abstract, transient, strict fields are ignored;
8284
- see JSON set/get/cast rules for Java object fields in the notes for JSON object
83-
and JSONAdapter;
84-
- Enum, synthetic and final fields are ignored.
85+
and JSONAdapter.
8586

8687
Constant:
8788
static final Object IGNORED; // returns from replacer/reviver to skip the field
@@ -97,7 +98,7 @@ Overview:
9798
// first call with object class name and json argument as value
9899
static boolean isClassName(String name);
99100
<T> T castMember(String memberName, JSON jsonObj, T sample);
100-
// returns the sample if member does not exists
101+
// returns the sample if JSON member does not exists
101102
protected void setIgnored(String[] fldNames); // set ignored field names
102103
protected String[] getIgnored()
103104

dist/json-2.0.0.jar

410 Bytes
Binary file not shown.

src/org/miktim/json/JSON.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
* - when the names within an object are not unique, parser stores the last value only;
1111
* - JSON object setter accepts any Java object, all Java primitives and primitive arrays;
1212
* - avoid recursion!;
13-
* - in addition, the generator converts Java Lists, Sets to JSON arrays
13+
* - in addition, the generator converts Java Collections to JSON arrays
1414
* and Java Maps to JSON objects. The null key is converted to a "null" member name.
15-
* Other Java objects are converted to JSON strings.
15+
* Other Java objects are converted to string representation.
1616
*
1717
* Created: 2020-03-07
1818
*/

src/org/miktim/json/JSONAdapter.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
/*
22
* JSONAdapter class. MIT (c) 2022 miktim@mail.ru
3-
* Cast by sample/class JSON variable to Java primitive or primitive array
3+
*
4+
* Casting by sample or Class of a JSON variable or array to a Java primitive or array.
5+
* - sample must be initialized;
6+
* - casting null to a Java primitive returns corresponding initial value;
7+
* - casting null to an array returns an empty array;
8+
* - casting null to String returns "null";
9+
* - casting null to other Java objects returns null;
10+
* - casting to null returns null.
11+
*
12+
* Created: march 2022
413
*/
514
package org.miktim.json;
615

src/org/miktim/json/JSONObject.java

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,19 @@
11
/*
2-
* JSONObject class. MIT (c) 2022 miktim@mail.ru
2+
* JSONObject abstract class. MIT (c) 2022 miktim@mail.ru
3+
*
4+
* Unloads/loads Java object accessible fields to/from JSON object.
5+
* - Java final, interface, abstract, transient, strict fields are ignored;
6+
* - see JSON set/get/cast rules for Java object fields in the notes for JSON object
7+
* and JSONAdapter.
8+
*
9+
* Created: april 2022
310
*/
411
package org.miktim.json;
512

613
import java.lang.reflect.Field;
714
import java.lang.reflect.Modifier;
815
import java.util.Arrays;
16+
import java.util.LinkedHashMap;
917

1018
public abstract class JSONObject {
1119

@@ -46,31 +54,32 @@ public static boolean isClassName(String fldName) {
4654
return true;
4755
}
4856

49-
private String[] _ignoredFields = new String[]{};//
57+
private String[] ignoredFields = new String[]{};//
5058

51-
protected boolean isIgnored(String fldName) {
52-
return Arrays.binarySearch(_ignoredFields, fldName) >= 0;
59+
protected final boolean isIgnored(String fldName) {
60+
return Arrays.binarySearch(ignoredFields, fldName) >= 0;
5361
}
5462

5563
protected void setIgnored(String[] fldNames) {
56-
_ignoredFields = fldNames.clone();
57-
Arrays.sort(_ignoredFields);
64+
ignoredFields = fldNames.clone();
65+
Arrays.sort(ignoredFields);
5866
}
5967

6068
protected String[] getIgnored() {
61-
return _ignoredFields;
69+
return ignoredFields;
6270
}
6371

6472
private Object toJSON(JSONObject jsonObj) // returns Object
6573
throws IllegalArgumentException, IllegalAccessException {
6674
String name = jsonObj.getClass().getName();
6775
Object json = jsonObj.replacer(name, new JSON());
6876
if (json instanceof JSON) {
69-
Field[] fields = jsonObj.getClass().getDeclaredFields();
70-
// Field[] fields = getFields(jsonObj);
77+
// Field[] fields = jsonObj.getClass().getDeclaredFields();
78+
Field[] fields = getAccessibleFields(jsonObj);
7179
for (Field field : fields) {
72-
if (!jsonObj.isIgnored(field)) {
73-
name = field.getName();
80+
name = field.getName();
81+
// if (!jsonObj.isIgnored(field)) {
82+
if (!jsonObj.isIgnored(name)) {
7483
field.setAccessible(true);
7584
Object value = jsonObj.replacer(name, field.get(jsonObj));
7685
if (value == null || !value.equals(IGNORED)) {
@@ -90,11 +99,12 @@ private JSONObject fromJSON(JSONObject jsonObj, Object json)
9099
String name = jsonObj.getClass().getName();
91100
json = jsonObj.reviver(name, json);
92101
if (json instanceof JSON) {
93-
Field[] fields = jsonObj.getClass().getDeclaredFields();
94-
// Field[] fields = getFields(jsonObj);
102+
// Field[] fields = jsonObj.getClass().getDeclaredFields();
103+
Field[] fields = getAccessibleFields(jsonObj);
95104
for (Field field : fields) {
96105
name = field.getName();
97-
if (!jsonObj.isIgnored(field) && ((JSON) json).exists(name)) {
106+
// if (!jsonObj.isIgnored(field) && ((JSON) json).exists(name)) {
107+
if (!jsonObj.isIgnored(name) && ((JSON) json).exists(name)) {
98108
field.setAccessible(true);
99109
Object newValue = jsonObj.reviver(name, ((JSON) json).get(name));
100110
Object value = field.get(jsonObj);
@@ -112,10 +122,35 @@ private JSONObject fromJSON(JSONObject jsonObj, Object json)
112122
return jsonObj;
113123
}
114124

125+
/*
115126
private boolean isIgnored(Field field) {
116127
return field.isSynthetic() || field.isEnumConstant() //|| field.isAccessible() deprecated
117128
|| isIgnored(field.getName())
118129
|| (field.getModifiers() & Modifier.FINAL) != 0;
130+
}*/
131+
132+
private Field[] getAccessibleFields(Object obj) {
133+
LinkedHashMap<String, Field> accessibleFields = new LinkedHashMap<>();
134+
Class cls = obj.getClass();
135+
Package pkg = cls.getPackage();
136+
int ignore = Modifier.FINAL | Modifier.TRANSIENT | Modifier.STRICT
137+
| Modifier.INTERFACE | Modifier.ABSTRACT;
138+
while (cls != null) {
139+
Field[] fields = cls.getDeclaredFields();
140+
// for different package ignore NATIVE
141+
int ignored = ignore | (pkg != cls.getPackage() ? Modifier.NATIVE : 0);
142+
for (Field field : fields) {
143+
String name = field.getName();
144+
if (!accessibleFields.containsKey(name)
145+
&& (field.getModifiers() & ignored) == 0) {
146+
accessibleFields.put(name, field);
147+
}
148+
}
149+
// for all super classes disable PRIVATE
150+
ignore |= Modifier.PRIVATE;
151+
cls = cls.getSuperclass();
152+
}
153+
return accessibleFields.values().toArray(new Field[]{});
119154
}
120155

121156
}

test/json/JSONObjectTest.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,15 @@
1212
public class JSONObjectTest extends JSONObject {
1313

1414
public static String mS = "mS value";
15-
public A mA = new A(); // A extends J
16-
protected B mB = new B(); // B extends A
17-
J mJ = new J(); // J extends JSONObject
1815
static final String mSf = "Final fields ignored";
16+
private double md = 3.14159;
1917
private int mi = 123;
2018
private String mSp = "mSp value";
2119

20+
public A mA = new A(); // A extends J
21+
protected B mB = new B(); // B extends A
22+
J mJ = new J(); // J extends JSONObject
23+
2224
public static void log(Object s) {
2325
System.out.println(s);
2426
}
@@ -54,9 +56,9 @@ class B extends A {
5456
protected Object replacer(String name, Object value) {
5557
logName(this, name); // logName(), log() inherited from J
5658
if (isClassName(name)) {
57-
// unload inherited
58-
((JSON) value).set("aS", aS).set("jc", getJc());
59-
log("Unloaded inherited A.aS, J.jc: " + aS + ", " + getJc());
59+
// unload by getter
60+
((JSON) value).set("jc", getJc());
61+
log("Unloaded by getter J.jc: " + getJc());
6062
}
6163
return value;
6264
}
@@ -65,10 +67,9 @@ protected Object replacer(String name, Object value) {
6567
protected Object reviver(String name, Object value) {
6668
logName(this, name);
6769
if (isClassName(name)) {
68-
// load inherited
69-
aS = castMember("aS", (JSON) value, aS);
70+
// load by setter
7071
setJc(castMember("jc", (JSON) value, getJc()));
71-
log("Loaded inherited A.aS, J.jc: " + aS + ", " + getJc());
72+
log("Loaded by setter J.jc: " + getJc());
7273
}
7374
return value;
7475
}

0 commit comments

Comments
 (0)