File: JsonSerializer.java

package info (click to toggle)
libwikidata-toolkit-java 0.17.0-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 4,996 kB
  • sloc: java: 38,944; xml: 1,662; sql: 52; makefile: 2
file content (259 lines) | stat: -rw-r--r-- 7,949 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
/*
 * #%L
 * Wikidata Toolkit Data Model
 * %%
 * Copyright (C) 2014 Wikidata Toolkit Developers
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

package org.wikidata.wdtk.datamodel.helpers;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wikidata.wdtk.datamodel.interfaces.EntityDocument;
import org.wikidata.wdtk.datamodel.interfaces.EntityDocumentDumpProcessor;
import org.wikidata.wdtk.datamodel.interfaces.EntityUpdate;
import org.wikidata.wdtk.datamodel.interfaces.ItemDocument;
import org.wikidata.wdtk.datamodel.interfaces.LexemeDocument;
import org.wikidata.wdtk.datamodel.interfaces.MediaInfoDocument;
import org.wikidata.wdtk.datamodel.interfaces.PropertyDocument;
import org.wikidata.wdtk.datamodel.interfaces.Statement;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
//import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;

/**
 * This class implements {@link EntityDocumentDumpProcessor} to provide a
 * serializer for {@link EntityDocument} objects in JSON.
 * <p>
 * The implementation does not check if {@link #open()} has been called before
 * the first document is serialized. It is the responsibility of the caller to
 * do this.
 * <p>
 * Implementations of the data model are expected to be appropriately serializable
 * to JSON with Jackson.
 *
 * @author Markus Kroetzsch
 *
 */
public class JsonSerializer implements EntityDocumentDumpProcessor {

	private static final Logger logger = LoggerFactory.getLogger(JsonSerializer.class);

	private static final byte[] JSON_START_LIST = "[\n".getBytes(StandardCharsets.UTF_8);
	private static final byte[] JSON_SEP = ",\n".getBytes(StandardCharsets.UTF_8);
	private static final byte[] JSON_END_LIST = "\n]".getBytes(StandardCharsets.UTF_8);

	/**
	 * The stream that the resulting JSON is written to.
	 */
	private final OutputStream outputStream;

	/**
	 * Object mapper that is used to serialize JSON.
	 */
	protected static final ObjectMapper mapper = new ObjectMapper();
	static {
		mapper.configure(JsonGenerator.Feature.AUTO_CLOSE_TARGET, false);
		/*
		 * Support for Optional properties.
		 */
		//mapper.registerModule(new Jdk8Module());
	}

	/**
	 * Counter for the number of documents serialized so far.
	 */
	private int entityDocumentCount;

	/**
	 * Creates a new JSON serializer that writes its output to the given stream.
	 * The output stream will be managed by the object, i.e., it will be closed
	 * when {@link #close()} is call ed.
	 *
	 * @param outputStream
	 *            the output stream to write to
	 */
	public JsonSerializer(OutputStream outputStream) {
		this.outputStream = outputStream;
	}

	@Override
	public void open() {
		this.entityDocumentCount = 0;

		try {
			this.outputStream.write(JSON_START_LIST);
		} catch (IOException e) {
			reportException(e);
		}
	}

	@Override
	public void processItemDocument(ItemDocument itemDocument) {
		serializeEntityDocument(itemDocument);
	}

	@Override
	public void processPropertyDocument(PropertyDocument propertyDocument) {
		serializeEntityDocument(propertyDocument);
	}

	@Override
	public void processLexemeDocument(LexemeDocument lexemeDocument) {
		serializeEntityDocument(lexemeDocument);
	}

	@Override
	public void processMediaInfoDocument(MediaInfoDocument mediaInfoDocument) {
		serializeEntityDocument(mediaInfoDocument);
	}

	@Override
	public void close() {
		try {
			this.outputStream.write(JSON_END_LIST);
			this.outputStream.close();
		} catch (IOException e) {
			reportException(e);
		}
	}

	/**
	 * Returns the number of entity documents serialized so far.
	 *
	 * @return number of serialized entity documents
	 */
	public int getEntityDocumentCount() {
		return this.entityDocumentCount;
	}

	/**
	 * Reports a given exception as a RuntimeException, since the interface does
	 * not allow us to throw checked exceptions directly.
	 *
	 * @param e
	 *            the exception to report
	 * @throws RuntimeException
	 *             in all cases
	 */
	private void reportException(Exception e) {
		logger.error("Failed to write JSON export: " + e.toString());
		throw new RuntimeException(e.toString(), e);
	}

	/**
	 * Writes the JSON serialization of the given {@link EntityDocument}.
	 *
	 * @param entityDocument
	 *            the document to serialize
	 */
	private void serializeEntityDocument(EntityDocument entityDocument) {
		try {
			if (this.entityDocumentCount > 0) {
				this.outputStream.write(JSON_SEP);
			}
			mapper.writeValue(this.outputStream, entityDocument);
		} catch (IOException e) {
			reportException(e);
		}
		this.entityDocumentCount++;
	}

	/**
	 * Serializes the given object in JSON and returns the resulting string.
	 * Throws if the serialization fails.
	 *
	 * @param entityDocument
	 *            object to serialize
	 * @return JSON serialization
	 * @throws JsonProcessingException if the object cannot be serialized
	 */
	public static String getJsonString(EntityDocument entityDocument) throws JsonProcessingException {
		return mapper.writeValueAsString(entityDocument);
	}

	/**
	 * Serializes the given object in JSON and returns the resulting string.
	 * Throws if the serialization fails.
	 *
	 * @param itemDocument
	 *            object to serialize
	 * @return JSON serialization
	 * @throws JsonProcessingException if the object cannot be serialized
	 */
	public static String getJsonString(ItemDocument itemDocument) throws JsonProcessingException {
		return mapper.writeValueAsString(itemDocument);
	}

	/**
	 * Serializes the given object in JSON and returns the resulting string.
	 * Throws if the serialization fails.
	 *
	 * @param propertyDocument
	 *            object to serialize
	 * @return JSON serialization
	 * @throws JsonProcessingException if the object cannot be serialized
	 */
	public static String getJsonString(PropertyDocument propertyDocument) throws JsonProcessingException {
		return mapper.writeValueAsString(propertyDocument);
	}

	/**
	 * Serializes the given object in JSON and returns the resulting string.
	 * Throws if the serialization fails.
	 *
	 * @param mediaInfoDocument
	 *            object to serialize
	 * @return JSON serialization
	 * @throws JsonProcessingException if the object cannot be serialized
	 */
	public static String getJsonString(MediaInfoDocument mediaInfoDocument) throws JsonProcessingException {
		return mapper.writeValueAsString(mediaInfoDocument);
	}

	/**
	 * Serializes the given object in JSON and returns the resulting string.
	 * Throws if the serialization fails.
	 *
	 * @param statement
	 *            object to serialize
	 * @return JSON serialization
	 * @throws JsonProcessingException if the object cannot be serialized
	 */
	public static String getJsonString(Statement statement) throws JsonProcessingException {
		return mapper.writeValueAsString(statement);
	}

	/**
	 * Serializes the given object in JSON and returns the resulting string.
	 * Throws if the serialization fails.
	 *
	 * @param update
	 *            object to serialize
	 * @return JSON serialization
	 * @throws JsonProcessingException if the object cannot be serialized
	 */
	public static String getJsonString(EntityUpdate update) throws JsonProcessingException {
		return mapper.writeValueAsString(update);
	}

}