[#5372] Add Result.formatJSON(JSONFormat) to allow for different JSON formats
This commit is contained in:
parent
33d56327c7
commit
48ea22d718
145
jOOQ/src/main/java/org/jooq/JSONFormat.java
Normal file
145
jOOQ/src/main/java/org/jooq/JSONFormat.java
Normal file
@ -0,0 +1,145 @@
|
||||
/**
|
||||
* Copyright (c) 2009-2016, Data Geekery GmbH (http://www.datageekery.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Other licenses:
|
||||
* -----------------------------------------------------------------------------
|
||||
* Commercial licenses for this work are available. These replace the above
|
||||
* ASL 2.0 and offer limited warranties, support, maintenance, and commercial
|
||||
* database integrations.
|
||||
*
|
||||
* For more information, please visit: http://www.jooq.org/licenses
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
package org.jooq;
|
||||
|
||||
/**
|
||||
* A JSON formatting type, which can be used to configure JSON imports /
|
||||
* exports.
|
||||
* <p>
|
||||
* The default format is the following, using {@link #header()} equal to
|
||||
* <code>true</code> and applying {@link RecordFormat#ARRAY}: <code><pre>
|
||||
* {"fields":[{"name":"field-1","type":"type-1"},
|
||||
* {"name":"field-2","type":"type-2"},
|
||||
* ...,
|
||||
* {"name":"field-n","type":"type-n"}],
|
||||
* "records":[[value-1-1,value-1-2,...,value-1-n],
|
||||
* [value-2-1,value-2-2,...,value-2-n]]}</pre></code>
|
||||
* <p>
|
||||
* If {@link #header()} is set to <code>false</code>, then the result is simply
|
||||
* the records array, either using {@link RecordFormat#ARRAY}: <code><pre>
|
||||
* [[value-1-1,value-1-2,...,value-1-n],
|
||||
* [value-2-1,value-2-2,...,value-2-n]]</pre></code>
|
||||
* <p>
|
||||
* or, using {@link RecordFormat#OBJECT}: <code><pre>
|
||||
* [{"field-1": value-1-1, "field-2": value-1-2,..., "field-n": value-1-n},
|
||||
* {"field-1": value-2-1, "field-2": value-2-2,..., "field-n": value-2-n}]</pre></code>
|
||||
*
|
||||
* @author Lukas Eder
|
||||
*/
|
||||
public final class JSONFormat {
|
||||
|
||||
final boolean header;
|
||||
final RecordFormat recordFormat;
|
||||
|
||||
public JSONFormat() {
|
||||
this(
|
||||
true,
|
||||
RecordFormat.ARRAY
|
||||
);
|
||||
}
|
||||
|
||||
private JSONFormat(
|
||||
boolean header,
|
||||
RecordFormat recordFormat) {
|
||||
this.header = header;
|
||||
this.recordFormat = recordFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to emit a header row with column names, defaulting to
|
||||
* <code>true</code>.
|
||||
*/
|
||||
public JSONFormat header(boolean newHeader) {
|
||||
return new JSONFormat(
|
||||
newHeader,
|
||||
recordFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to emit a header row with column names, defaulting to
|
||||
* <code>true</code>.
|
||||
*/
|
||||
public boolean header() {
|
||||
return header;
|
||||
}
|
||||
|
||||
/**
|
||||
* The record format to be applied, defaulting to
|
||||
* {@link RecordFormat#ARRAY}.
|
||||
*/
|
||||
public JSONFormat recordFormat(RecordFormat newRecordFormat) {
|
||||
return new JSONFormat(
|
||||
header,
|
||||
newRecordFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
* The record format to be applied, defaulting to
|
||||
* {@link RecordFormat#ARRAY}.
|
||||
*/
|
||||
public RecordFormat recordFormat() {
|
||||
return recordFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* The format of individual JSON records.
|
||||
*/
|
||||
public enum RecordFormat {
|
||||
|
||||
/**
|
||||
* A record is a JSON array.
|
||||
* <p>
|
||||
* This format allows for accessing columns by index, saving space by
|
||||
* avoiding repetitive column names in large result sets. Use this
|
||||
* preferrably with {@link JSONFormat#header()} equal to
|
||||
* <code>true</code>.
|
||||
*/
|
||||
ARRAY,
|
||||
|
||||
/**
|
||||
* A record is a JSON object.
|
||||
* <p>
|
||||
* This format allows for accessing columns by name, repeating column
|
||||
* names in each record.
|
||||
*/
|
||||
OBJECT,
|
||||
}
|
||||
}
|
||||
@ -607,6 +607,15 @@ public interface Result<R extends Record> extends List<R>, Attachable {
|
||||
*/
|
||||
String formatJSON();
|
||||
|
||||
/**
|
||||
* Get a simple formatted representation of this result as a JSON data
|
||||
* structure, according to the format.
|
||||
*
|
||||
* @return The formatted result
|
||||
* @see JSONFormat
|
||||
*/
|
||||
String formatJSON(JSONFormat format);
|
||||
|
||||
/**
|
||||
* Get this result formatted as XML.
|
||||
*
|
||||
@ -711,6 +720,13 @@ public interface Result<R extends Record> extends List<R>, Attachable {
|
||||
*/
|
||||
void formatJSON(OutputStream stream) throws IOException;
|
||||
|
||||
/**
|
||||
* Like {@link #formatJSON(JSONFormat)}, but the data is output onto an {@link OutputStream}.
|
||||
*
|
||||
* @throws IOException - an unchecked wrapper for {@link java.io.IOException}, if anything goes wrong.
|
||||
*/
|
||||
void formatJSON(OutputStream stream, JSONFormat format) throws IOException;
|
||||
|
||||
/**
|
||||
* Like {@link #formatXML()}, but the data is output onto an {@link OutputStream}.
|
||||
*
|
||||
@ -809,6 +825,13 @@ public interface Result<R extends Record> extends List<R>, Attachable {
|
||||
*/
|
||||
void formatJSON(Writer writer) throws IOException;
|
||||
|
||||
/**
|
||||
* Like {@link #formatJSON(JSONFormat)}, but the data is output onto a {@link Writer}.
|
||||
*
|
||||
* @throws IOException - an unchecked wrapper for {@link java.io.IOException}, if anything goes wrong.
|
||||
*/
|
||||
void formatJSON(Writer writer, JSONFormat format) throws IOException;
|
||||
|
||||
/**
|
||||
* Like {@link #formatXML()}, but the data is output onto a {@link Writer}.
|
||||
*
|
||||
|
||||
@ -86,6 +86,7 @@ import org.jooq.DataType;
|
||||
import org.jooq.EnumType;
|
||||
import org.jooq.Field;
|
||||
import org.jooq.ForeignKey;
|
||||
import org.jooq.JSONFormat;
|
||||
import org.jooq.Name;
|
||||
import org.jooq.Record;
|
||||
import org.jooq.Record1;
|
||||
@ -125,6 +126,7 @@ import org.jooq.exception.InvalidResultException;
|
||||
import org.jooq.tools.Convert;
|
||||
import org.jooq.tools.StringUtils;
|
||||
import org.jooq.tools.jdbc.MockResultSet;
|
||||
import org.jooq.tools.json.JSONArray;
|
||||
import org.jooq.tools.json.JSONObject;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
@ -870,57 +872,98 @@ final class ResultImpl<R extends Record> implements Result<R>, AttachableInterna
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String formatJSON(JSONFormat format) {
|
||||
StringWriter writer = new StringWriter();
|
||||
formatJSON(writer, format);
|
||||
return writer.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void formatJSON(OutputStream stream) {
|
||||
formatJSON(new OutputStreamWriter(stream));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void formatJSON(OutputStream stream, JSONFormat format) {
|
||||
formatJSON(new OutputStreamWriter(stream), format);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void formatJSON(Writer writer) {
|
||||
formatJSON(writer, new JSONFormat());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void formatJSON(Writer writer, JSONFormat format) {
|
||||
try {
|
||||
List<Map<String, String>> f = new ArrayList<Map<String, String>>();
|
||||
List<List<Object>> r = new ArrayList<List<Object>>();
|
||||
List<Map<String, String>> f = null;
|
||||
List<Object> r = new ArrayList<Object>();
|
||||
|
||||
Map<String, String> fieldMap;
|
||||
for (Field<?> field : fields.fields) {
|
||||
fieldMap = new LinkedHashMap<String, String>();
|
||||
if (format.header()) {
|
||||
f = new ArrayList<Map<String, String>>();
|
||||
|
||||
if (field instanceof TableField) {
|
||||
Table<?> table = ((TableField<?, ?>) field).getTable();
|
||||
for (Field<?> field : fields.fields) {
|
||||
Map<String, String> fieldMap = new LinkedHashMap<String, String>();
|
||||
|
||||
if (table != null) {
|
||||
Schema schema = table.getSchema();
|
||||
if (field instanceof TableField) {
|
||||
Table<?> table = ((TableField<?, ?>) field).getTable();
|
||||
|
||||
if (schema != null) {
|
||||
fieldMap.put("schema", schema.getName());
|
||||
if (table != null) {
|
||||
Schema schema = table.getSchema();
|
||||
|
||||
if (schema != null)
|
||||
fieldMap.put("schema", schema.getName());
|
||||
|
||||
fieldMap.put("table", table.getName());
|
||||
}
|
||||
|
||||
fieldMap.put("table", table.getName());
|
||||
}
|
||||
|
||||
fieldMap.put("name", field.getName());
|
||||
fieldMap.put("type", field.getDataType().getTypeName().toUpperCase());
|
||||
|
||||
f.add(fieldMap);
|
||||
}
|
||||
|
||||
fieldMap.put("name", field.getName());
|
||||
fieldMap.put("type", field.getDataType().getTypeName().toUpperCase());
|
||||
|
||||
f.add(fieldMap);
|
||||
}
|
||||
|
||||
for (Record record : this) {
|
||||
List<Object> list = new ArrayList<Object>();
|
||||
switch (format.recordFormat()) {
|
||||
case ARRAY:
|
||||
for (Record record : this) {
|
||||
List<Object> list = new ArrayList<Object>();
|
||||
|
||||
for (int index = 0; index < fields.fields.length; index++) {
|
||||
list.add(formatJSON0(record.get(index)));
|
||||
}
|
||||
for (int index = 0; index < fields.fields.length; index++)
|
||||
list.add(formatJSON0(record.get(index)));
|
||||
|
||||
r.add(list);
|
||||
r.add(list);
|
||||
}
|
||||
|
||||
break;
|
||||
case OBJECT:
|
||||
for (Record record : this) {
|
||||
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||
|
||||
for (int index = 0; index < fields.fields.length; index++)
|
||||
map.put(record.field(index).getName(), formatJSON0(record.get(index)));
|
||||
|
||||
r.add(map);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Format not supported: " + format);
|
||||
}
|
||||
|
||||
Map<String, List<?>> map = new LinkedHashMap<String, List<?>>();
|
||||
if (f == null) {
|
||||
writer.append(JSONArray.toJSONString(r));
|
||||
}
|
||||
else {
|
||||
Map<String, List<?>> map = new LinkedHashMap<String, List<?>>();
|
||||
|
||||
map.put("fields", f);
|
||||
map.put("records", r);
|
||||
map.put("fields", f);
|
||||
map.put("records", r);
|
||||
|
||||
writer.append(JSONObject.toJSONString(map));
|
||||
writer.append(JSONObject.toJSONString(map));
|
||||
}
|
||||
|
||||
writer.flush();
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user