diff --git a/jOOQ/src/main/java/org/jooq/JSONFormat.java b/jOOQ/src/main/java/org/jooq/JSONFormat.java index f4d7bcb4b2..829867bf18 100644 --- a/jOOQ/src/main/java/org/jooq/JSONFormat.java +++ b/jOOQ/src/main/java/org/jooq/JSONFormat.java @@ -65,8 +65,8 @@ import static org.jooq.tools.StringUtils.rightPad; */ public final class JSONFormat { - public static final JSONFormat DEFAULT_FOR_RESULTS = new JSONFormat(); - public static final JSONFormat DEFAULT_FOR_RECORDS = new JSONFormat().header(false); + public final static JSONFormat DEFAULT_FOR_RESULTS = new JSONFormat(); + public final static JSONFormat DEFAULT_FOR_RECORDS = new JSONFormat().header(false); final boolean format; final String newline; @@ -74,6 +74,7 @@ public final class JSONFormat { final String[] indented; final boolean header; final RecordFormat recordFormat; + final boolean quoteNested; public JSONFormat() { this( @@ -82,7 +83,8 @@ public final class JSONFormat { 2, null, true, - RecordFormat.ARRAY + RecordFormat.ARRAY, + false ); } @@ -92,7 +94,8 @@ public final class JSONFormat { int indent, String[] indented, boolean header, - RecordFormat recordFormat + RecordFormat recordFormat, + boolean quoteNested ) { this.format = format; this.newline = newline; @@ -105,75 +108,79 @@ public final class JSONFormat { }; this.header = header; this.recordFormat = recordFormat; + this.quoteNested = quoteNested; } /** * The new value for the formatting flag, defaulting to false. */ - public JSONFormat format(boolean newFormat) { + public final JSONFormat format(boolean newFormat) { return new JSONFormat( newFormat, newline, indent, null, header, - recordFormat + recordFormat, + quoteNested ); } /** * The formatting flag. */ - public boolean format() { + public final boolean format() { return format; } /** * The new newline character, defaulting to \n. */ - public JSONFormat newline(String newNewline) { + public final JSONFormat newline(String newNewline) { return new JSONFormat( format, newNewline, indent, indented, header, - recordFormat + recordFormat, + quoteNested ); } /** * The formatting flag. */ - public String newline() { + public final String newline() { return format ? newline : ""; } /** * The new indentation value, defaulting to 2. */ - public JSONFormat indent(int newIndent) { + public final JSONFormat indent(int newIndent) { return new JSONFormat( format, newline, newIndent, null, header, - recordFormat + recordFormat, + quoteNested ); } /** * The indentation. */ - public int indent() { + public final int indent() { return indent; } /** * Convenience method to get an indentation string at a given level. */ - public String indentString(int level) { + public final String indentString(int level) { if (level < indented.length) return indented[level]; else if (format) @@ -186,14 +193,15 @@ public final class JSONFormat { * Whether to emit a header row with column names, defaulting to * true. */ - public JSONFormat header(boolean newHeader) { + public final JSONFormat header(boolean newHeader) { return new JSONFormat( format, newline, indent, indented, newHeader, - recordFormat + recordFormat, + quoteNested ); } @@ -201,7 +209,7 @@ public final class JSONFormat { * Whether to emit a header row with column names, defaulting to * true. */ - public boolean header() { + public final boolean header() { return header; } @@ -209,14 +217,15 @@ public final class JSONFormat { * The record format to be applied, defaulting to * {@link RecordFormat#ARRAY}. */ - public JSONFormat recordFormat(RecordFormat newRecordFormat) { + public final JSONFormat recordFormat(RecordFormat newRecordFormat) { return new JSONFormat( format, newline, indent, indented, header, - newRecordFormat + newRecordFormat, + quoteNested ); } @@ -224,10 +233,34 @@ public final class JSONFormat { * The record format to be applied, defaulting to * {@link RecordFormat#ARRAY}. */ - public RecordFormat recordFormat() { + public final RecordFormat recordFormat() { return recordFormat; } + /** + * Whether nested {@link JSON} or {@link JSONB} content should be quoted + * like a string, or nested into JSON formatted output. + */ + public final JSONFormat quoteNested(boolean newQuoteNested) { + return new JSONFormat( + format, + newline, + indent, + indented, + header, + recordFormat, + newQuoteNested + ); + } + + /** + * Whether nested {@link JSON} or {@link JSONB} content should be quoted + * like a string, or nested into JSON formatted output. + */ + public final boolean quoteNested() { + return quoteNested; + } + /** * The format of individual JSON records. */ diff --git a/jOOQ/src/main/java/org/jooq/XMLFormat.java b/jOOQ/src/main/java/org/jooq/XMLFormat.java index 12a4267217..b9b03937dd 100644 --- a/jOOQ/src/main/java/org/jooq/XMLFormat.java +++ b/jOOQ/src/main/java/org/jooq/XMLFormat.java @@ -46,8 +46,8 @@ import static org.jooq.tools.StringUtils.rightPad; */ public final class XMLFormat { - public static final XMLFormat DEFAULT_FOR_RESULTS = new XMLFormat(); - public static final XMLFormat DEFAULT_FOR_RECORDS = new XMLFormat().header(false).xmlns(false); + public final static XMLFormat DEFAULT_FOR_RESULTS = new XMLFormat(); + public final static XMLFormat DEFAULT_FOR_RECORDS = new XMLFormat().header(false).xmlns(false); final boolean xmlns; final boolean format; @@ -56,6 +56,7 @@ public final class XMLFormat { final String[] indented; final boolean header; final RecordFormat recordFormat; + final boolean quoteNested; public XMLFormat() { this( @@ -65,7 +66,8 @@ public final class XMLFormat { 2, null, true, - RecordFormat.VALUE_ELEMENTS_WITH_FIELD_ATTRIBUTE + RecordFormat.VALUE_ELEMENTS_WITH_FIELD_ATTRIBUTE, + false ); } @@ -76,7 +78,8 @@ public final class XMLFormat { int indent, String[] indented, boolean header, - RecordFormat recordFormat + RecordFormat recordFormat, + boolean quoteNested ) { this.xmlns = xmlns; this.format = format; @@ -90,12 +93,13 @@ public final class XMLFormat { }; this.header = header; this.recordFormat = recordFormat; + this.quoteNested = quoteNested; } /** * The new value for the xmlns flag, defaulting to true. */ - public XMLFormat xmlns(boolean newXmlns) { + public final XMLFormat xmlns(boolean newXmlns) { return new XMLFormat( newXmlns, format, @@ -103,21 +107,22 @@ public final class XMLFormat { indent, indented, header, - recordFormat + recordFormat, + quoteNested ); } /** * The xmlns flag. */ - public boolean xmlns() { + public final boolean xmlns() { return xmlns; } /** * The new value for the formatting flag, defaulting to false. */ - public XMLFormat format(boolean newFormat) { + public final XMLFormat format(boolean newFormat) { return new XMLFormat( xmlns, newFormat, @@ -125,21 +130,22 @@ public final class XMLFormat { indent, null, header, - recordFormat + recordFormat, + quoteNested ); } /** * The formatting flag. */ - public boolean format() { + public final boolean format() { return format; } /** * The new newline character, defaulting to \n. */ - public XMLFormat newline(String newNewline) { + public final XMLFormat newline(String newNewline) { return new XMLFormat( xmlns, format, @@ -147,21 +153,22 @@ public final class XMLFormat { indent, indented, header, - recordFormat + recordFormat, + quoteNested ); } /** * The formatting flag. */ - public String newline() { + public final String newline() { return format ? newline : ""; } /** * The new indentation value, defaulting to 2. */ - public XMLFormat indent(int newIndent) { + public final XMLFormat indent(int newIndent) { return new XMLFormat( xmlns, format, @@ -169,21 +176,22 @@ public final class XMLFormat { newIndent, null, header, - recordFormat + recordFormat, + quoteNested ); } /** * The indentation. */ - public int indent() { + public final int indent() { return indent; } /** * Convenience method to get an indentation string at a given level. */ - public String indentString(int level) { + public final String indentString(int level) { if (level < indented.length) return indented[level]; else if (format) @@ -201,7 +209,7 @@ public final class XMLFormat { * This flag is ignored on {@link Record#formatXML(XMLFormat)} and similar * methods. */ - public XMLFormat header(boolean newHeader) { + public final XMLFormat header(boolean newHeader) { return new XMLFormat( xmlns, format, @@ -209,14 +217,15 @@ public final class XMLFormat { indent, indented, newHeader, - recordFormat + recordFormat, + quoteNested ); } /** * The header. */ - public boolean header() { + public final boolean header() { return header; } @@ -224,7 +233,7 @@ public final class XMLFormat { * The record format to be applied, defaulting to * {@link RecordFormat#VALUE_ELEMENTS_WITH_FIELD_ATTRIBUTE}. */ - public XMLFormat recordFormat(RecordFormat newRecordFormat) { + public final XMLFormat recordFormat(RecordFormat newRecordFormat) { return new XMLFormat( xmlns, format, @@ -232,7 +241,8 @@ public final class XMLFormat { indent, indented, header, - newRecordFormat + newRecordFormat, + quoteNested ); } @@ -240,10 +250,35 @@ public final class XMLFormat { * The record format to be applied, defaulting to * {@link RecordFormat#VALUE_ELEMENTS_WITH_FIELD_ATTRIBUTE}. */ - public RecordFormat recordFormat() { + public final RecordFormat recordFormat() { return recordFormat; } + /** + * Whether nested {@link XML} content should be quoted like a string, or + * nested into XML formatted output. + */ + public final XMLFormat quoteNested(boolean newQuoteNested) { + return new XMLFormat( + xmlns, + format, + newline, + indent, + indented, + header, + recordFormat, + newQuoteNested + ); + } + + /** + * Whether nested {@link XML} content should be quoted like a string, or + * nested into XML formatted output. + */ + public final boolean quoteNested() { + return quoteNested; + } + /** * The format of individual XML records. */ diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractCursor.java b/jOOQ/src/main/java/org/jooq/impl/AbstractCursor.java index c575179d71..e9387786ba 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractCursor.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractCursor.java @@ -77,6 +77,8 @@ import org.jooq.DataType; import org.jooq.EnumType; import org.jooq.Field; import org.jooq.Formattable; +import org.jooq.JSON; +import org.jooq.JSONB; import org.jooq.JSONFormat; import org.jooq.Name; import org.jooq.Record; @@ -88,6 +90,7 @@ import org.jooq.TXTFormat; import org.jooq.Table; import org.jooq.TableField; import org.jooq.TableRecord; +import org.jooq.XML; import org.jooq.XMLFormat; import org.jooq.exception.IOException; import org.jooq.tools.StringUtils; @@ -684,6 +687,13 @@ abstract class AbstractCursor extends AbstractFormattable impl ((Formattable) value).formatJSON(writer, format); } + else if (value instanceof JSON && !format.quoteNested()) { + writer.write(((JSON) value).data()); + } + else if (value instanceof JSONB && !format.quoteNested()) { + writer.write(((JSONB) value).data()); + } + else { JSONValue.writeJSONString(value, writer); } @@ -846,6 +856,8 @@ abstract class AbstractCursor extends AbstractFormattable impl if (value instanceof Formattable) ((Formattable) value).formatXML(writer, format); + else if (value instanceof XML && !format.quoteNested()) + writer.append(((XML) value).data()); else writer.append(escapeXML(format0(value, false, false))); diff --git a/jOOQ/src/main/java/org/jooq/impl/LoaderImpl.java b/jOOQ/src/main/java/org/jooq/impl/LoaderImpl.java index 76c58e2df0..7b5d88fb5f 100644 --- a/jOOQ/src/main/java/org/jooq/impl/LoaderImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/LoaderImpl.java @@ -793,7 +793,7 @@ final class LoaderImpl implements // [#5200] When the primary key is not supplied in the data, // we'll assume it uses an identity, and there will never be duplicates - // [#10358] The above should be moved inside InsertQueryImpl + // [#10358] TODO: The above should be moved inside InsertQueryImpl // [#7253] Use native onDuplicateKeyIgnore() support else if (onDuplicate == ON_DUPLICATE_KEY_IGNORE && primaryKey.cardinality() > 0) { insert.onDuplicateKeyIgnore(true);