Skip to content

Commit fd7f6b8

Browse files
author
mgeipel
committed
Library independent Json encoder added
1 parent 64d0c60 commit fd7f6b8

File tree

1 file changed

+119
-0
lines changed

1 file changed

+119
-0
lines changed
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/*
2+
* Copyright 2013 Deutsche Nationalbibliothek
3+
*
4+
* Licensed under the Apache License, Version 2.0 the "License";
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.culturegraph.mf.stream.converter;
17+
18+
import java.util.Deque;
19+
import java.util.LinkedList;
20+
21+
import org.apache.commons.lang.StringEscapeUtils;
22+
import org.culturegraph.mf.framework.DefaultStreamPipe;
23+
import org.culturegraph.mf.framework.ObjectReceiver;
24+
import org.culturegraph.mf.framework.StreamReceiver;
25+
import org.culturegraph.mf.framework.annotations.Description;
26+
import org.culturegraph.mf.framework.annotations.In;
27+
import org.culturegraph.mf.framework.annotations.Out;
28+
29+
/**
30+
* Serialises an object as JSON. Records and entities are represented as objects
31+
* unless their name ends with []. If the name ends with [], an array is
32+
* created.
33+
*
34+
* @author Markus Geipel
35+
*
36+
*/
37+
@Description("Serialises an object as JSON")
38+
@In(StreamReceiver.class)
39+
@Out(String.class)
40+
public final class SimpleJsonEncoder extends DefaultStreamPipe<ObjectReceiver<String>> {
41+
42+
public static final String ARRAY_MARKER = "[]";
43+
44+
private StringBuilder builder = new StringBuilder();
45+
private final Deque<Character> bracketStack = new LinkedList<Character>();
46+
private final Deque<Boolean> commaStack = new LinkedList<Boolean>();
47+
private boolean commaNeeded;
48+
49+
50+
@Override
51+
public void startRecord(final String id) {
52+
builder.append('{');
53+
bracketStack.push(Character.valueOf('}'));
54+
}
55+
56+
@Override
57+
public void endRecord() {
58+
builder.append('}');
59+
bracketStack.clear();
60+
getReceiver().process(builder.toString());
61+
builder = new StringBuilder();
62+
commaStack.clear();
63+
}
64+
65+
@Override
66+
public void startEntity(final String name) {
67+
68+
if (commaNeeded) {
69+
builder.append(", ");
70+
}
71+
commaNeeded = true;
72+
73+
if (name.endsWith(ARRAY_MARKER)) {
74+
builder.append("\"" + escape(name.substring(0, name.length() - ARRAY_MARKER.length())) + "\": [ ");
75+
bracketStack.push(Character.valueOf(']'));
76+
} else {
77+
if (inArray()) {
78+
builder.append(" { ");
79+
} else {
80+
builder.append("\"" + escape(name) + "\": { ");
81+
}
82+
83+
bracketStack.push(Character.valueOf('}'));
84+
}
85+
commaStack.push(Boolean.valueOf(commaNeeded));
86+
commaNeeded = false;
87+
}
88+
89+
private static String escape(final String string) {
90+
return StringEscapeUtils.escapeJavaScript(string);
91+
}
92+
93+
@Override
94+
public void endEntity() {
95+
builder.append(bracketStack.pop() + " ");
96+
commaNeeded = commaStack.pop().booleanValue();
97+
}
98+
99+
@Override
100+
public void literal(final String name, final String value) {
101+
102+
if (commaNeeded) {
103+
builder.append(", ");
104+
}
105+
106+
if (inArray()) {
107+
builder.append("\"" + escape(value) + "\"");
108+
} else {
109+
builder.append("\"" + escape(name) + "\":\"" + escape(value) + "\"");
110+
}
111+
112+
commaNeeded = true;
113+
}
114+
115+
private boolean inArray() {
116+
return bracketStack.peek().charValue() == ']';
117+
}
118+
119+
}

0 commit comments

Comments
 (0)