This repository has been archived by the owner on Jan 21, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 24
/
JSONNode.java
112 lines (97 loc) · 4.51 KB
/
JSONNode.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package fmpp.models;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import fmpp.util.StringUtil;
import freemarker.template.AdapterTemplateModel;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateNodeModel;
/**
* Node in a hierarchy of JSON values. See http://www.json.org/ for JSON types; each has its own subclass.
* JSON "object" and "array" values are the non-leafs in the tree.
*/
public abstract class JSONNode implements TemplateNodeModel, AdapterTemplateModel, Serializable {
private static final long serialVersionUID = 1L;
private final JSONNode parentNode;
private final String nodeName;
/**
* Returns the FTL node name for a node that has otherwise no name.
*/
protected static String nodeTypeToDefaultNodeName(String nodeType) {
return "unnamed" + StringUtil.capitalizeFirst(nodeType);
}
/**
* @param parentNode the JSON "object" or JSON "array" that contains this value.
* @param nodeName {@code null}, unless this is the value in a key-value pair, in which case it's the key.
* When it's {@code null}, the actual node name will be {@link #getDefaultNodeName()}.
*/
protected JSONNode(JSONNode parentNode, String nodeName) {
this.parentNode = parentNode;
this.nodeName = nodeName != null ? nodeName : getDefaultNodeName();
}
/**
* Returns the name of the node if it has no explicit name. This is normally called by the
* {@link #JSONNode(JSONNode, String)} constructor if its second argument is {@code null}.
*
* @see #nodeTypeToDefaultNodeName(String)
*/
protected abstract String getDefaultNodeName();
/**
* Returns the JSON "object" or JSON "array" that contains this value.
*/
public final TemplateNodeModel getParentNode() throws TemplateModelException {
return parentNode;
}
/**
* Returns the same as {@link #getNodeType()}, except when the node is the value in a key-value pair in a
* JSON object, in which case it returns the key value.
*/
public final String getNodeName() throws TemplateModelException {
return nodeName;
}
public final String getNodeNamespace() throws TemplateModelException {
return null;
}
/**
* Wraps a {@link List}, a {@link Map} with string keys, a {@link String}, a {@link Number} or a {@link Boolean}
* into a {@link JSONNode}. The values in the {@link List} or {@link Map} must be also be one of the previously
* listed types. The resulting object is NOT thread safe. Also, the wrapped objects shouldn't be changed after the
* wrapping. The wrapping of the contained values is possibly lazy.
* @return The wrapped value; note the this will return {@code null} for JSON null values, not a
* {@link JSONNullNode} instance.
* @throws TemplateModelException If {@code obj} can't be wrapped into JSON node.
*/
public static JSONNode wrap(Object jsonPOJO) throws TemplateModelException {
return wrap(jsonPOJO, null, null, false);
}
/**
* @param parentNode Same as the similar parameter of {@link #JSONNode(JSONNode, String)}.
* @param nodeName Same as the similar parameter of {@link #JSONNode(JSONNode, String)}.
* @throws TemplateModelException If {@code obj} can't be wrapped into JSON node.
*/
@SuppressWarnings("unchecked")
protected static JSONNode wrap(Object obj, JSONNode parentNode, String nodeName, boolean wrapNullAsJSONNullNode)
throws TemplateModelException {
if (obj == null) {
return wrapNullAsJSONNullNode ? new JSONNullNode(parentNode, nodeName) : null;
}
if (obj instanceof String) {
return new JSONStringNode(parentNode, nodeName, (String) obj);
}
if (obj instanceof Number) {
return new JSONNumberNode(parentNode, nodeName, (Number) obj);
}
if (obj instanceof Boolean) {
return new JSONBooleanNode(parentNode, nodeName, ((Boolean) obj).booleanValue());
}
if (obj instanceof List) {
return new JSONArrayNode(parentNode, nodeName, (List<Object>) obj);
}
if (obj instanceof Map) {
// Let's hope it has String keys...
return new JSONObjectNode(parentNode, nodeName, (Map<String, Object>) obj);
}
throw new TemplateModelException("Can't warp an object of this class as JSON node: "
+ obj.getClass().getName());
}
}