Skip to content

Commit fc0e421

Browse files
authored
Added purejson lib
1 parent a8eeff6 commit fc0e421

File tree

10 files changed

+406
-13
lines changed

10 files changed

+406
-13
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ It covers the following libraries:
2828
* [minimal-json](https://github.com/ralfstx/minimal-json)
2929
* [mjson](https://github.com/bolerio/mjson)
3030
* [underscore-java](https://github.com/javadev/underscore-java)
31+
* [purejson](https://senthilganeshs.github.io/jsonp/)
3132

3233
When available, both databinding and 'stream' (custom packing and unpacking) implementations are tested.
3334
Two different kinds of [models](/src/main/java/com/github/fabienrenaud/jjb/model/) are evaluated with payloads of 1, 10, 100 and 1000 KB size:
@@ -70,6 +71,7 @@ The results here-below were computed on April the 8th, 2018 with the following l
7071
| tapestry | 5.4.3 |
7172
| jsoniter | 0.9.22 |
7273
| minimal-json | 0.9.5 |
74+
| purejson | 1.0.1 |
7375

7476
[All graphs and sheets are available in this google doc.][spreadsheet]
7577

build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ dependencies {
8484
compile group: 'org.sharegov', name: 'mjson', version: '1.4.1'
8585
// underscore-java
8686
compile group: 'com.github.javadev', name: 'underscore', version: '1.37'
87+
//purejson
88+
compile group: 'io.github.senthilganeshs', name: 'purejson', version: '1.0.1'
8789

8890
// Test
8991
testCompile group: 'junit', name: 'junit', version: '4.12'

src/main/java/com/github/fabienrenaud/jjb/JsonBench.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,4 +110,8 @@ public Object mjson() throws Exception {
110110
public Object underscore_java() throws Exception {
111111
return null;
112112
}
113+
114+
public Object purejson() throws Exception {
115+
return null;
116+
}
113117
}

src/main/java/com/github/fabienrenaud/jjb/stream/Deserialization.java

Lines changed: 274 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,36 @@
11
package com.github.fabienrenaud.jjb.stream;
22

3+
import java.io.BufferedInputStream;
4+
import java.io.ByteArrayInputStream;
5+
import java.io.IOException;
6+
import java.io.InputStream;
7+
import java.math.BigDecimal;
8+
import java.time.LocalDate;
9+
import java.time.OffsetDateTime;
10+
import java.util.ArrayList;
11+
import java.util.List;
12+
import java.util.UUID;
13+
import java.util.concurrent.atomic.AtomicBoolean;
14+
import java.util.concurrent.atomic.AtomicReference;
15+
16+
import org.json.JSONException;
17+
import org.json.JSONObject;
18+
import org.openjdk.jmh.annotations.Benchmark;
19+
320
import com.fasterxml.jackson.core.JsonParser;
421
import com.github.fabienrenaud.jjb.JsonBench;
522
import com.github.fabienrenaud.jjb.data.JsonSource;
23+
import com.github.fabienrenaud.jjb.model.Clients;
24+
import com.github.fabienrenaud.jjb.model.Clients.Client;
25+
import com.github.fabienrenaud.jjb.model.Clients.EyeColor;
26+
import com.github.fabienrenaud.jjb.model.Clients.Partner;
27+
import com.github.fabienrenaud.jjb.model.Users;
28+
import com.github.fabienrenaud.jjb.model.Users.Friend;
29+
import com.github.fabienrenaud.jjb.model.Users.User;
630
import com.owlike.genson.stream.ObjectReader;
7-
import org.json.JSONException;
8-
import org.json.JSONObject;
9-
import org.openjdk.jmh.annotations.Benchmark;
1031

11-
import java.io.IOException;
32+
import io.github.senthilganeshs.parser.json.Parser;
33+
import io.github.senthilganeshs.parser.json.Parser.Value;
1234

1335
/**
1436
* @author Fabien Renaud
@@ -106,4 +128,251 @@ public Object mjson() throws Exception {
106128
public Object underscore_java() throws Exception {
107129
return JSON_SOURCE().streamDeserializer().underscore_java(JSON_SOURCE().nextString());
108130
}
109-
}
131+
132+
@Benchmark
133+
@Override
134+
public Object purejson() throws Exception {
135+
final AtomicReference<Object> ref = new AtomicReference<>();
136+
try (final InputStream is = new ByteArrayInputStream(JSON_SOURCE().nextByteArray())) {
137+
Parser.create()
138+
.parse(is)
139+
.ifSuccess(v -> ref.set(PureJson.toObject(v))) //construct object if success.
140+
.ifFailure(msg -> {
141+
throw new RuntimeException(msg);
142+
}); //crash if exception
143+
return ref.get();
144+
}
145+
}
146+
147+
148+
interface PureJson {
149+
static Object toObject(final Value v) {
150+
List<User> users = new ArrayList<>();
151+
List<Client> clients = new ArrayList<>();
152+
153+
final AtomicBoolean isUser = new AtomicBoolean(false);
154+
v.isJSON((k, jv) -> k.isString(key ->
155+
jv.isArray(av -> {
156+
if (key.equals("users")) {
157+
users.add(toUser(av));
158+
isUser.set(true);
159+
} else if (key.equals("clients")) {
160+
clients.add(toClient(av));
161+
isUser.set(false);
162+
}
163+
})));
164+
165+
if (isUser.get()) {
166+
Users us = new Users();
167+
us.users = users;
168+
return us;
169+
} else {
170+
Clients cs = new Clients();
171+
cs.clients = clients;
172+
return cs;
173+
}
174+
}
175+
176+
static Client toClient(final Value v) {
177+
final Client client = new Client();
178+
v.isJSON((k, jv) -> k.isString(key -> {
179+
switch (key) {
180+
case "_id":
181+
jv.isInteger(id -> client._id = id);
182+
break;
183+
case "index":
184+
jv.isInteger(index -> client.index = index.intValue());
185+
break;
186+
case "guid":
187+
jv.isInteger(guid -> client.guid = UUID.fromString(guid.toString()));
188+
break;
189+
case "isActive":
190+
jv.isBool(isActive -> client.isActive = isActive);
191+
break;
192+
case "balance":
193+
jv.isDouble(balance -> client.balance = new BigDecimal(balance));
194+
break;
195+
case "picture":
196+
jv.isString(picture -> client.picture = picture);
197+
break;
198+
case "age":
199+
jv.isInteger(age -> client.age = age.intValue());
200+
break;
201+
case "eyeColor":
202+
jv.isInteger(ec -> client.eyeColor = EyeColor.fromNumber(ec.intValue()));
203+
break;
204+
case "name":
205+
jv.isString(name -> client.name = name);
206+
break;
207+
case "gender":
208+
jv.isString(gender -> client.gender = gender);
209+
break;
210+
case "company":
211+
jv.isString(company -> client.company = company);
212+
break;
213+
case "emails":
214+
List<String> emails = new ArrayList<>();
215+
jv.isArray(av -> av
216+
.isString(emails::add));
217+
client.emails = emails.toArray(new String[0]);
218+
break;
219+
case "phones":
220+
List<Long> phones = new ArrayList<>();
221+
jv.isArray(av -> av
222+
.isInteger(phones::add));
223+
long[] ps = new long[phones.size()];
224+
for (int i = 0; i < phones.size(); i++) {
225+
ps[i] = phones.get(i);
226+
}
227+
client.phones = ps;
228+
break;
229+
case "address":
230+
jv.isString(address -> client.address = address);
231+
break;
232+
case "about":
233+
jv.isString(about -> client.about = about);
234+
break;
235+
case "registered":
236+
jv.isString(registered -> client.registered = LocalDate.parse(registered));
237+
break;
238+
case "latitude":
239+
jv.isDouble(latitude -> client.latitude = latitude);
240+
break;
241+
case "longitude":
242+
jv.isDouble(longitude -> client.longitude = longitude);
243+
break;
244+
case "tags":
245+
final List<String> tags = new ArrayList<>();
246+
jv.isArray(av -> av
247+
.isString(tags::add));
248+
client.tags = tags;
249+
break;
250+
case "partners":
251+
final List<Partner> partners = new ArrayList<>();
252+
final List<Long> ids = new ArrayList<>();
253+
final List<String> names = new ArrayList<>();
254+
final List<OffsetDateTime> since = new ArrayList<>();
255+
256+
jv.isArray(av -> av
257+
.isJSON((ak, ajv) -> ak.isString(ajk -> {
258+
switch (ajk) {
259+
case "id":
260+
ajv.isInteger(ids::add);
261+
break;
262+
case "name":
263+
ajv.isString(names::add);
264+
break;
265+
case "since":
266+
ajv.isString(time -> since.add(OffsetDateTime.parse(time)));
267+
break;
268+
}
269+
})));
270+
271+
for (int i = 0; i < ids.size(); i++) {
272+
partners.add(Partner.create(ids.get(i), names.get(i), since.get(i)));
273+
}
274+
client.partners = partners;
275+
break;
276+
}
277+
}));
278+
279+
return client;
280+
}
281+
282+
static User toUser(final Value v) {
283+
final User user = new User();
284+
v.isJSON((jk, jv) -> jk.isString(key -> {
285+
switch (key) {
286+
case "_id":
287+
jv.isString(id -> user._id = id);
288+
break;
289+
case "index":
290+
jv.isInteger(index -> user.index = index.intValue());
291+
break;
292+
case "guid":
293+
jv.isString(guid -> user.guid = guid);
294+
break;
295+
case "isActive":
296+
jv.isBool(isActive -> user.isActive = isActive);
297+
break;
298+
case "balance":
299+
jv.isString(balance -> user.balance = balance);
300+
break;
301+
case "picture":
302+
jv.isString(picture -> user.picture = picture);
303+
break;
304+
case "age":
305+
jv.isInteger(age -> user.age = age.intValue());
306+
break;
307+
case "eyeColor":
308+
jv.isString(ec -> user.eyeColor = ec);
309+
break;
310+
case "name":
311+
jv.isString(name -> user.name = name);
312+
break;
313+
case "gender":
314+
jv.isString(gender -> user.gender = gender);
315+
break;
316+
case "company":
317+
jv.isString(company -> user.company = company);
318+
break;
319+
case "email":
320+
jv.isString(email -> user.email = email);
321+
break;
322+
case "phone":
323+
jv.isString(phone -> user.phone = phone);
324+
break;
325+
case "address":
326+
jv.isString(address -> user.address = address);
327+
break;
328+
case "about":
329+
jv.isString(about -> user.about = about);
330+
break;
331+
case "registered":
332+
jv.isString(registered -> user.registered = registered);
333+
break;
334+
case "latitude":
335+
jv.isDouble(latitude -> user.latitude = latitude);
336+
break;
337+
case "longitude":
338+
jv.isDouble(longitude -> user.longitude = longitude);
339+
break;
340+
case "tags":
341+
final List<String> tags = new ArrayList<>();
342+
jv.isArray(__v -> __v.isString(tags::add));
343+
user.tags = tags;
344+
break;
345+
case "friends":
346+
final List<Friend> friends = new ArrayList<>();
347+
final List<String> ids = new ArrayList<>();
348+
final List<String> names = new ArrayList<>();
349+
350+
jv.isArray(jav -> jav
351+
.isJSON((jak, jajv) -> jak.isString(jakk -> {
352+
switch (jakk) {
353+
case "id":
354+
jajv.isString(ids::add);
355+
break;
356+
case "name":
357+
jajv.isString(names::add);
358+
break;
359+
}
360+
})));
361+
362+
for (int i = 0; i < ids.size(); i++) {
363+
friends.add(Friend.create(ids.get(i), names.get(i)));
364+
}
365+
user.friends = friends;
366+
break;
367+
case "greeting":
368+
jv.isString(greeting -> user.greeting = greeting);
369+
break;
370+
case "favoriteFruit":
371+
jv.isString(fav -> user.favoriteFruit = fav);
372+
break;
373+
}
374+
}));
375+
return user;
376+
}
377+
}
378+
}

src/main/java/com/github/fabienrenaud/jjb/stream/Serialization.java

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
package com.github.fabienrenaud.jjb.stream;
22

3+
import java.io.ByteArrayOutputStream;
4+
import java.io.OutputStreamWriter;
5+
import java.io.Writer;
6+
7+
import org.openjdk.jmh.annotations.Benchmark;
8+
39
import com.fasterxml.jackson.core.JsonGenerator;
410
import com.github.fabienrenaud.jjb.JsonBench;
511
import com.github.fabienrenaud.jjb.JsonUtils;
612
import com.github.fabienrenaud.jjb.data.JsonSource;
713
import com.grack.nanojson.JsonAppendableWriter;
814
import com.owlike.genson.stream.ObjectWriter;
15+
16+
import io.github.senthilganeshs.parser.json.Generator;
17+
import io.github.senthilganeshs.parser.json.Parser.Value;
918
import okio.BufferedSink;
1019
import okio.Okio;
11-
import org.openjdk.jmh.annotations.Benchmark;
12-
13-
import java.io.ByteArrayOutputStream;
14-
import java.io.OutputStreamWriter;
15-
import java.io.Writer;
1620

1721
/**
1822
* @author Fabien Renaud
@@ -140,4 +144,11 @@ public Object mjson() throws Exception {
140144
public Object underscore_java() throws Exception {
141145
return JSON_SOURCE().streamSerializer().underscore_java(JSON_SOURCE().nextPojo());
142146
}
147+
148+
@Benchmark
149+
@Override
150+
public Object purejson() throws Exception {
151+
Value purejson = JSON_SOURCE().streamSerializer().purejson(JSON_SOURCE().nextPojo());
152+
return Generator.create().generate(purejson);
153+
}
143154
}

src/main/java/com/github/fabienrenaud/jjb/stream/StreamSerializer.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
import com.google.gson.stream.JsonWriter;
55
import com.grack.nanojson.JsonAppendableWriter;
66
import com.owlike.genson.stream.ObjectWriter;
7+
8+
import io.github.senthilganeshs.parser.json.Parser.Value;
9+
710
import org.json.JSONException;
811

912
import java.io.IOException;
@@ -33,4 +36,6 @@ public interface StreamSerializer<T> {
3336
mjson.Json mjson(final T obj) throws IOException;
3437

3538
Object underscore_java(final T obj) throws IOException;
39+
40+
Value purejson(final T obj) throws IOException;
3641
}

0 commit comments

Comments
 (0)