Skip to content

Commit add61d8

Browse files
committed
Added encoder for encoding strings in JSON format
1 parent cce0e2d commit add61d8

File tree

3 files changed

+226
-0
lines changed

3 files changed

+226
-0
lines changed

pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,11 @@
258258
<artifactId>jdom</artifactId>
259259
<version>1.1</version>
260260
</dependency>
261+
<dependency>
262+
<groupId>com.fasterxml.jackson.core</groupId>
263+
<artifactId>jackson-core</artifactId>
264+
<version>2.1.4</version>
265+
</dependency>
261266
</dependencies>
262267

263268

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
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.io.IOException;
19+
import java.io.StringWriter;
20+
21+
import org.culturegraph.mf.exceptions.MetafactureException;
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+
import com.fasterxml.jackson.core.JsonFactory;
30+
import com.fasterxml.jackson.core.JsonGenerationException;
31+
import com.fasterxml.jackson.core.JsonGenerator;
32+
import com.fasterxml.jackson.core.JsonStreamContext;
33+
34+
/**
35+
* Serialises an object as JSON. Records and entities are represented
36+
* as objects unless their name ends with []. If the name ends with [],
37+
* an array is created.
38+
*
39+
* @author Christoph Böhme
40+
*
41+
*/
42+
@Description("Serialises an object as JSON")
43+
@In(StreamReceiver.class)
44+
@Out(String.class)
45+
public final class JsonEncoder extends
46+
DefaultStreamPipe<ObjectReceiver<String>> {
47+
48+
public static final String ARRAY_MARKER = "[]";
49+
50+
private final JsonGenerator jsonGenerator;
51+
private final StringWriter writer = new StringWriter();
52+
53+
public JsonEncoder() {
54+
try {
55+
jsonGenerator = new JsonFactory().createGenerator(writer);
56+
} catch (IOException e) {
57+
throw new MetafactureException(e);
58+
}
59+
}
60+
61+
@Override
62+
public void startRecord(final String id) {
63+
final StringBuffer buffer = writer.getBuffer();
64+
buffer.delete(0, buffer.length());
65+
startGroup(id);
66+
}
67+
68+
@Override
69+
public void endRecord() {
70+
endGroup();
71+
try {
72+
jsonGenerator.flush();
73+
} catch (IOException e) {
74+
throw new MetafactureException(e);
75+
}
76+
getReceiver().process(writer.toString());
77+
}
78+
79+
@Override
80+
public void startEntity(final String name) {
81+
startGroup(name);
82+
}
83+
84+
@Override
85+
public void endEntity() {
86+
endGroup();
87+
}
88+
89+
@Override
90+
public void literal(final String name, final String value) {
91+
try {
92+
if (jsonGenerator.getOutputContext().inObject()) {
93+
jsonGenerator.writeFieldName(name);
94+
}
95+
if (value == null) {
96+
jsonGenerator.writeNull();
97+
} else {
98+
jsonGenerator.writeString(value);
99+
}
100+
} catch (JsonGenerationException e) {
101+
throw new MetafactureException(e);
102+
}
103+
catch (IOException e) {
104+
throw new MetafactureException(e);
105+
}
106+
}
107+
108+
private void startGroup(final String name) {
109+
try {
110+
final JsonStreamContext ctx = jsonGenerator.getOutputContext();
111+
if (name.endsWith(ARRAY_MARKER)) {
112+
if (!ctx.inRoot()) {
113+
jsonGenerator.writeFieldName(name.substring(0, name.length() - ARRAY_MARKER.length()));
114+
}
115+
jsonGenerator.writeStartArray();
116+
} else {
117+
if (!ctx.inRoot()) {
118+
jsonGenerator.writeFieldName(name);
119+
}
120+
jsonGenerator.writeStartObject();
121+
}
122+
} catch (JsonGenerationException e) {
123+
throw new MetafactureException(e);
124+
}
125+
catch (IOException e) {
126+
throw new MetafactureException(e);
127+
}
128+
}
129+
130+
private void endGroup() {
131+
try {
132+
final JsonStreamContext ctx = jsonGenerator.getOutputContext();
133+
if (ctx.inObject()) {
134+
jsonGenerator.writeEndObject();
135+
} else if (ctx.inArray()) {
136+
jsonGenerator.writeEndArray();
137+
}
138+
} catch (JsonGenerationException e) {
139+
throw new MetafactureException(e);
140+
}
141+
catch (IOException e) {
142+
throw new MetafactureException(e);
143+
}
144+
}
145+
146+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
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 static org.junit.Assert.assertEquals;
19+
20+
import org.culturegraph.mf.framework.DefaultObjectReceiver;
21+
import org.junit.Test;
22+
23+
/**
24+
* Test for {@link JsonEncoder}.
25+
*
26+
* @author Christoph Böhme
27+
*
28+
*/
29+
public final class JsonEncoderTest {
30+
31+
private static final String SIMPLE_JSON = "{\"lit1\":\"val1\",\"ent1\":{\"lit2\":\"val2\",\"lit3\":\"val3\"}}";
32+
private static final String LIST_JSON = "{\"list\":[\"1\",\"2\",\"3\"],\"lit\":\"val\"}";
33+
34+
@Test
35+
public void testSimpleJson() {
36+
final JsonEncoder encoder = new JsonEncoder();
37+
encoder.setReceiver(new DefaultObjectReceiver<String>() {
38+
@Override
39+
public void process(final String str) {
40+
assertEquals(SIMPLE_JSON, str);
41+
}
42+
});
43+
44+
encoder.startRecord("");
45+
encoder.literal("lit1", "val1");
46+
encoder.startEntity("ent1");
47+
encoder.literal("lit2", "val2");
48+
encoder.literal("lit3", "val3");
49+
encoder.endEntity();
50+
encoder.endRecord();
51+
encoder.closeStream();
52+
}
53+
54+
@Test
55+
public void testListJson() {
56+
final JsonEncoder encoder = new JsonEncoder();
57+
encoder.setReceiver(new DefaultObjectReceiver<String>() {
58+
@Override
59+
public void process(final String str) {
60+
assertEquals(LIST_JSON, str);
61+
}
62+
});
63+
64+
encoder.startRecord("");
65+
encoder.startEntity("list[]");
66+
encoder.literal("", "1");
67+
encoder.literal("", "2");
68+
encoder.literal("", "3");
69+
encoder.endEntity();
70+
encoder.literal("lit", "val");
71+
encoder.endRecord();
72+
encoder.closeStream();
73+
}
74+
75+
}

0 commit comments

Comments
 (0)