1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.opencastproject.util;
23
24 import static org.opencastproject.util.data.Monadics.mlist;
25
26 import org.opencastproject.util.data.Collections;
27 import org.opencastproject.util.data.Function;
28 import org.opencastproject.util.data.Function2;
29 import org.opencastproject.util.data.Monadics;
30 import org.opencastproject.util.data.Option;
31 import org.opencastproject.util.data.Prelude;
32
33 import org.json.simple.JSONArray;
34 import org.json.simple.JSONObject;
35
36 import java.util.ArrayList;
37 import java.util.Date;
38 import java.util.List;
39
40
41 public final class Jsons {
42 private Jsons() {
43 }
44
45
46 public static final Function<Val, Boolean> notZero = new Function<Val, Boolean>() {
47 @Override public Boolean apply(Val val) {
48 return !ZERO_VAL.equals(val);
49 }
50 };
51
52
53 public static final Function<Prop, Val> getVal = new Function<Prop, Val>() {
54 @Override public Val apply(Prop prop) {
55 return prop.getVal();
56 }
57 };
58
59
60 public static final Val NULL = new Val() {
61 };
62
63
64 public static final Val ZERO_VAL = new Val() {
65 };
66
67
68 public static final Obj ZERO_OBJ = obj();
69
70
71 public static final Arr ZERO_ARR = arr();
72
73 public static final class Prop {
74 private final String name;
75 private final Val val;
76
77 private Prop(String name, Val val) {
78 this.name = name;
79 this.val = val;
80 }
81
82 public String getName() {
83 return name;
84 }
85
86 public Val getVal() {
87 return val;
88 }
89 }
90
91
92 public abstract static class Val {
93 }
94
95 private static final class SVal extends Val {
96 private final Object val;
97
98 private SVal(Object val) {
99 this.val = val;
100 }
101
102 public Object getVal() {
103 return val;
104 }
105 }
106
107 public static final class Obj extends Val {
108 private final List<Prop> props;
109
110 private Obj(List<Prop> props) {
111 this.props = props;
112 }
113
114 public List<Prop> getProps() {
115 return props;
116 }
117
118 public Obj append(Obj o) {
119 if (!ZERO_OBJ.equals(o))
120 return new Obj(Collections.<Prop, List>concat(props, o.getProps()));
121 else
122 return o;
123 }
124
125 public String toJson() {
126 return Jsons.toJson(this);
127 }
128 }
129
130 public static final class Arr extends Val {
131 private final List<Val> vals;
132
133 public Arr(List<Val> vals) {
134 this.vals = vals;
135 }
136
137 public List<Val> getVals() {
138 return vals;
139 }
140
141 public String toJson() {
142 return Jsons.toJson(this);
143 }
144 }
145
146
147
148 public static String toJson(Obj obj) {
149 return toJsonSimple(obj).toString();
150 }
151
152 public static String toJson(Arr arr) {
153 return toJsonSimple(arr).toString();
154 }
155
156 private static JSONObject toJsonSimple(Obj obj) {
157 return mlist(obj.getProps()).foldl(new JSONObject(), new Function2<JSONObject, Prop, JSONObject>() {
158 @Override public JSONObject apply(JSONObject jo, Prop prop) {
159 jo.put(prop.getName(), toJsonSimple(prop.getVal()));
160 return jo;
161 }
162 });
163 }
164
165 private static JSONArray toJsonSimple(Arr arr) {
166 return mlist(arr.getVals()).foldl(new JSONArray(), new Function2<JSONArray, Val, JSONArray>() {
167 @Override public JSONArray apply(JSONArray ja, Val val) {
168 ja.add(toJsonSimple(val));
169 return ja;
170 }
171 });
172 }
173
174 private static Object toJsonSimple(Val val) {
175 if (val instanceof SVal) {
176 return ((SVal) val).getVal();
177 }
178 if (val instanceof Obj) {
179 return toJsonSimple((Obj) val);
180 }
181 if (val instanceof Arr) {
182 return toJsonSimple((Arr) val);
183 }
184 if (val.equals(NULL)) {
185 return null;
186 }
187 return Prelude.unexhaustiveMatch();
188 }
189
190
191 public static Obj obj(Prop... ps) {
192 return new Obj(mlist(ps).filter(notZero.o(getVal)).value());
193 }
194
195
196 public static Arr arr(Val... vs) {
197 return new Arr(mlist(vs).filter(notZero).value());
198 }
199
200
201 public static Arr arr(List<Val> vs) {
202 return new Arr(mlist(vs).filter(notZero).value());
203 }
204
205
206 public static Arr arr(Monadics.ListMonadic<Val> vs) {
207 return new Arr(vs.filter(notZero).value());
208 }
209
210 public static Val v(Number v) {
211 return new SVal(v);
212 }
213
214 public static Val v(String v) {
215 return new SVal(v);
216 }
217
218 public static final Function<String, Val> stringVal = new Function<String, Val>() {
219 @Override public Val apply(String s) {
220 return v(s);
221 }
222 };
223
224 public static Val v(Boolean v) {
225 return new SVal(v);
226 }
227
228 public static Val v(Date v) {
229 return new SVal(DateTimeSupport.toUTC(v.getTime()));
230 }
231
232
233 public static Prop p(String key, Val val) {
234 return new Prop(key, val);
235 }
236
237
238 public static Prop p(String key, Option<Val> val) {
239 return new Prop(key, val.getOrElse(ZERO_VAL));
240 }
241
242
243 public static Prop p(String key, Number value) {
244 return new Prop(key, v(value));
245 }
246
247
248 public static Prop p(String key, String value) {
249 return new Prop(key, v(value));
250 }
251
252
253 public static Prop p(String key, Boolean value) {
254 return new Prop(key, v(value));
255 }
256
257
258 public static Obj append(Obj... os) {
259 final List<Prop> props = mlist(os).foldl(new ArrayList<Prop>(), new Function2<ArrayList<Prop>, Obj, ArrayList<Prop>>() {
260 @Override public ArrayList<Prop> apply(ArrayList<Prop> props, Obj obj) {
261 props.addAll(obj.getProps());
262 return props;
263 }
264 });
265 return new Obj(props);
266 }
267
268
269 public static Arr append(Arr... as) {
270 final List<Val> vals = mlist(as).foldl(new ArrayList<Val>(), new Function2<ArrayList<Val>, Arr, ArrayList<Val>>() {
271 @Override public ArrayList<Val> apply(ArrayList<Val> vals, Arr arr) {
272 vals.addAll(arr.getVals());
273 return vals;
274 }
275 });
276 return new Arr(vals);
277 }
278 }