EN
Java - how to create custom json builder?
8 points
In Java it is very easy to create own JSON builder. This article shows how to create it.
Presented source code consist of:
Program.java
file that contains simple usage example of json builder,JsonBuilder.java
file that contains common json builder logic,ArrayJsonBuilder.java
file that contains array json builder logic,ObjectJsonBuilder.java
file that contains object json builder logic,Encoder.java
file that is used to escapse dangerous characters inside strings.
Program.java
file:
xxxxxxxxxx
1
package com.dirask.json;
2
3
public class Program {
4
public static void main(String[] args) {
5
ObjectJsonBuilder studentBuilder = new ObjectJsonBuilder();
6
7
studentBuilder.addNumber("id", 1000);
8
studentBuilder.addString("name", "John");
9
studentBuilder.addNumber("age", 25);
10
studentBuilder.addBoolean("isStudent", true);
11
12
ArrayJsonBuilder todosBuilder = studentBuilder.createArray("todos");
13
14
ObjectJsonBuilder todo1 = todosBuilder.createObject();
15
todo1.addNumber("priority", 5);
16
todo1.addString("name", "Go to classes");
17
18
ObjectJsonBuilder todo2 = todosBuilder.createObject();
19
todo2.addNumber("priority", 1);
20
todo2.addString("name", "Go to party");
21
22
ObjectJsonBuilder todo3 = todosBuilder.createObject();
23
todo3.addNumber("priority", 4);
24
todo3.addString("name", "Go to lecture");
25
26
System.out.println(studentBuilder.extractJson());
27
28
29
ArrayJsonBuilder fruitsBuilder = new ArrayJsonBuilder();
30
31
fruitsBuilder.addString("Apples");
32
fruitsBuilder.addString("Grapes");
33
fruitsBuilder.addString("Bananas");
34
35
System.out.println(fruitsBuilder.extractJson());
36
}
37
}
38
Output:
xxxxxxxxxx
1
{
2
"id":1000,
3
"name":"John",
4
"age":25,
5
"isStudent":true,
6
"todos":[
7
{"priority":5,"name":"Go to classes"},
8
{"priority":1,"name":"Go to party"},
9
{"priority":4,"name":"Go to lecture"}
10
]
11
}
12
13
["Apples","Grapes","Bananas"]
JsonBuilder.java
file:
xxxxxxxxxx
1
package com.dirask.json;
2
3
public abstract class JsonBuilder {
4
private boolean empty = true;
5
private boolean locked = false;
6
7
private StringBuilder builder;
8
private JsonBuilder entity = null; // keeps reference to sub-json builder
9
10
private Locker parentLocker;
11
private Locker localLocker;
12
13
private String json = null;
14
15
public JsonBuilder() {
16
this.builder = new StringBuilder();
17
18
this.parentLocker = null;
19
this.localLocker = this.createLocker();
20
}
21
22
protected JsonBuilder(StringBuilder builder, Locker locker) {
23
this.builder = builder;
24
25
this.parentLocker = locker;
26
this.localLocker = this.createLocker();
27
28
locker.lock();
29
}
30
31
protected Locker createLocker() {
32
Locker locker = new Locker() {
33
34
public void lock() {
35
locked = true;
36
}
37
38
39
public void unlock() {
40
locked = false;
41
}
42
};
43
44
return locker;
45
}
46
47
public boolean isLocked() {
48
return this.locked;
49
}
50
51
public boolean isEmpty() {
52
return this.empty;
53
}
54
55
protected void appendText(String text) {
56
this.builder.append(text);
57
}
58
59
protected void cleanupEntity() {
60
if (this.entity == null)
61
return;
62
63
this.entity.cleanupEntity();
64
this.entity.finaliseJson();
65
66
this.entity = null;
67
}
68
69
protected void appendSeparator() {
70
if (this.empty)
71
this.empty = false;
72
73
else
74
this.builder.append(",");
75
}
76
77
protected ArrayJsonBuilder createArray() {
78
ArrayJsonBuilder entity = new ArrayJsonBuilder(this.builder, this.localLocker);
79
this.entity = entity;
80
81
return entity;
82
}
83
84
protected ObjectJsonBuilder createObject() {
85
ObjectJsonBuilder entity = new ObjectJsonBuilder(this.builder, this.localLocker);
86
this.entity = entity;
87
88
return entity;
89
}
90
91
protected boolean finaliseJson() {
92
if (this.locked)
93
return false;
94
95
this.locked = true;
96
97
if (this.parentLocker != null)
98
this.parentLocker.unlock();
99
100
return true;
101
}
102
103
public String extractJson() {
104
if (this.json == null && this.parentLocker == null) {
105
this.cleanupEntity();
106
this.finaliseJson();
107
108
this.json = this.builder.toString();
109
}
110
111
return this.json;
112
}
113
114
protected interface Locker {
115
void lock();
116
117
void unlock();
118
}
119
}
ArrayJsonBuilder.java
file:
xxxxxxxxxx
1
package com.dirask.json;
2
3
public class ArrayJsonBuilder extends JsonBuilder {
4
public ArrayJsonBuilder() {
5
this.appendText("[");
6
}
7
8
protected ArrayJsonBuilder(StringBuilder builder, Locker locker) {
9
super(builder, locker);
10
11
builder.append("[");
12
}
13
14
private boolean addValue(Object value) {
15
super.cleanupEntity();
16
17
if (super.isLocked())
18
return false;
19
20
super.appendSeparator();
21
super.appendText(value == null ? "null" : value.toString());
22
23
return true;
24
}
25
26
public boolean addBoolean(Boolean value) {
27
return this.addValue(value);
28
}
29
30
public boolean addNumber(Number value) {
31
return this.addValue(value);
32
}
33
34
public boolean addString(String value) {
35
super.cleanupEntity();
36
37
if (super.isLocked())
38
return false;
39
40
super.appendSeparator();
41
42
if (value == null)
43
super.appendText("null");
44
45
else {
46
super.appendText("\"");
47
super.appendText(Encoder.encodeText(value));
48
super.appendText("\"");
49
}
50
51
return true;
52
}
53
54
public boolean addJson(JsonBuilder value) {
55
return this.addValue(value.extractJson());
56
}
57
58
59
public ArrayJsonBuilder createArray() {
60
super.cleanupEntity();
61
62
if (super.isLocked())
63
return null;
64
65
super.appendSeparator();
66
67
return super.createArray();
68
}
69
70
71
public ObjectJsonBuilder createObject() {
72
super.cleanupEntity();
73
74
if (super.isLocked())
75
return null;
76
77
super.appendSeparator();
78
79
return super.createObject();
80
}
81
82
83
protected boolean finaliseJson() {
84
if (super.finaliseJson()) {
85
super.appendText("]");
86
87
return true;
88
}
89
90
return false;
91
}
92
}
ObjectJsonBuilder.java
file:
xxxxxxxxxx
1
package com.dirask.json;
2
3
public class ObjectJsonBuilder extends JsonBuilder {
4
public ObjectJsonBuilder() {
5
this.appendText("{");
6
}
7
8
protected ObjectJsonBuilder(StringBuilder builder, Locker locker) {
9
super(builder, locker);
10
11
builder.append("{");
12
}
13
14
private boolean addValue(String name, Object value) {
15
super.cleanupEntity();
16
17
if (super.isLocked())
18
return false;
19
20
super.appendSeparator();
21
22
super.appendText("\"");
23
super.appendText(name);
24
super.appendText("\":");
25
super.appendText(value == null ? "null" : value.toString());
26
27
return true;
28
}
29
30
public boolean addBoolean(String name, Boolean value) {
31
return this.addValue(name, value);
32
}
33
34
public boolean addNumber(String name, Number value) {
35
return this.addValue(name, value);
36
}
37
38
public boolean addString(String name, String value) {
39
super.cleanupEntity();
40
41
if (super.isLocked())
42
return false;
43
44
super.appendSeparator();
45
46
super.appendText("\"");
47
super.appendText(name);
48
49
if (value == null)
50
super.appendText("\":null");
51
52
else {
53
super.appendText("\":\"");
54
super.appendText(Encoder.encodeText(value));
55
super.appendText("\"");
56
}
57
58
return true;
59
}
60
61
public boolean addBuilder(String name, JsonBuilder value) {
62
return this.addValue(name, value.extractJson());
63
}
64
65
public ArrayJsonBuilder createArray(String name) {
66
super.cleanupEntity();
67
68
if (super.isLocked())
69
return null;
70
71
super.appendSeparator();
72
73
super.appendText("\"");
74
super.appendText(name);
75
super.appendText("\":");
76
77
return super.createArray();
78
}
79
80
public ObjectJsonBuilder createObject(String name) {
81
super.cleanupEntity();
82
83
if (super.isLocked())
84
return null;
85
86
super.appendSeparator();
87
88
super.appendText("\"");
89
super.appendText(name);
90
super.appendText("\":");
91
92
return super.createObject();
93
}
94
95
96
protected boolean finaliseJson() {
97
if (super.finaliseJson()) {
98
super.appendText("}");
99
100
return true;
101
}
102
103
return false;
104
}
105
}
Encoder.java
file:
xxxxxxxxxx
1
package com.dirask.json;
2
3
public class Encoder {
4
private static String createHexString(int value) {
5
String text = Integer.toHexString(value);
6
7
if (value < 0x10)
8
return "{0" + text.toUpperCase() + "}";
9
10
return "{" + text.toUpperCase() + "}";
11
}
12
13
public static String encodeText(String text) {
14
int length = text.length();
15
16
if (length == 0)
17
return new String();
18
19
StringBuilder builder = new StringBuilder(length);
20
21
for (int i = 0; i < length; ++i) {
22
char tmp = text.charAt(i);
23
24
switch (tmp) {
25
case 0x00: // \0 - NULL
26
case 0x01:
27
case 0x02:
28
case 0x03:
29
case 0x04:
30
case 0x05:
31
case 0x06:
32
case 0x07:
33
case 0x08:
34
builder.append(createHexString(tmp));
35
continue;
36
37
case 0x09: // \t - TABULATOR
38
builder.append("\\t");
39
continue;
40
41
case 0x0A: // \n - NEW LINE
42
builder.append("\\n");
43
continue;
44
45
case 0x0B:
46
case 0x0C:
47
builder.append(createHexString(tmp));
48
continue;
49
50
case 0x0D: // \r - CARRIAGE RETURN
51
builder.append("\\r");
52
continue;
53
54
case 0x0E:
55
case 0x0F:
56
case 0x10:
57
case 0x11:
58
case 0x12:
59
case 0x13:
60
case 0x14:
61
case 0x15:
62
case 0x16:
63
case 0x17:
64
case 0x18:
65
case 0x19:
66
case 0x1A:
67
case 0x1B:
68
case 0x1C:
69
case 0x1D:
70
case 0x1E:
71
case 0x1F:
72
builder.append(createHexString(tmp));
73
continue;
74
75
// allowed characters
76
77
case 0x22: // " - DOUBLE QUOTATION MARK
78
builder.append("\\\"");
79
continue;
80
81
// allowed characters
82
83
case 0x5C: // \ - BACK SLASH
84
builder.append("\\\\");
85
continue;
86
87
// allowed characters
88
89
default:
90
builder.append(tmp);
91
}
92
}
93
94
return builder.toString();
95
}
96
}