diff --git a/jOOQ/src/main/java/org/jooq/JSONFormat.java b/jOOQ/src/main/java/org/jooq/JSONFormat.java index a1a9032ec5..28c443b649 100644 --- a/jOOQ/src/main/java/org/jooq/JSONFormat.java +++ b/jOOQ/src/main/java/org/jooq/JSONFormat.java @@ -39,6 +39,9 @@ package org.jooq; import static org.jooq.tools.StringUtils.rightPad; +import java.util.Base64; +import java.util.HexFormat; + import org.jetbrains.annotations.NotNull; /** @@ -87,6 +90,7 @@ public final class JSONFormat { boolean quoteNested; boolean nanAsString; boolean infinityAsString; + BinaryFormat binaryFormat; public JSONFormat() { this( @@ -103,7 +107,8 @@ public final class JSONFormat { true, false, false, - false + false, + BinaryFormat.BASE64 ); } @@ -121,7 +126,8 @@ public final class JSONFormat { boolean wrapSingleColumnRecords, boolean quoteNested, boolean nanAsString, - boolean infinityAsString + boolean infinityAsString, + BinaryFormat binaryFormat ) { this.mutable = mutable; this.format = format; @@ -142,6 +148,7 @@ public final class JSONFormat { this.quoteNested = quoteNested; this.nanAsString = nanAsString; this.infinityAsString = infinityAsString; + this.binaryFormat = binaryFormat; } /** @@ -171,7 +178,8 @@ public final class JSONFormat { wrapSingleColumnRecords, quoteNested, nanAsString, - infinityAsString + infinityAsString, + binaryFormat ); else return this; @@ -201,7 +209,8 @@ public final class JSONFormat { wrapSingleColumnRecords, quoteNested, nanAsString, - infinityAsString + infinityAsString, + binaryFormat ); } @@ -236,7 +245,8 @@ public final class JSONFormat { wrapSingleColumnRecords, quoteNested, nanAsString, - infinityAsString + infinityAsString, + binaryFormat ); } @@ -272,7 +282,8 @@ public final class JSONFormat { wrapSingleColumnRecords, quoteNested, nanAsString, - infinityAsString + infinityAsString, + binaryFormat ); } @@ -307,7 +318,8 @@ public final class JSONFormat { wrapSingleColumnRecords, quoteNested, nanAsString, - infinityAsString + infinityAsString, + binaryFormat ); } @@ -358,7 +370,8 @@ public final class JSONFormat { wrapSingleColumnRecords, quoteNested, nanAsString, - infinityAsString + infinityAsString, + binaryFormat ); } @@ -395,7 +408,8 @@ public final class JSONFormat { wrapSingleColumnRecords, quoteNested, nanAsString, - infinityAsString + infinityAsString, + binaryFormat ); } @@ -433,7 +447,8 @@ public final class JSONFormat { wrapSingleColumnRecords, quoteNested, nanAsString, - infinityAsString + infinityAsString, + binaryFormat ); } @@ -471,7 +486,8 @@ public final class JSONFormat { wrapSingleColumnRecords, quoteNested, nanAsString, - infinityAsString + infinityAsString, + binaryFormat ); } @@ -508,7 +524,8 @@ public final class JSONFormat { newWrapSingleColumnRecords, quoteNested, nanAsString, - infinityAsString + infinityAsString, + binaryFormat ); } @@ -544,7 +561,8 @@ public final class JSONFormat { wrapSingleColumnRecords, newQuoteNested, nanAsString, - infinityAsString + infinityAsString, + binaryFormat ); } @@ -582,7 +600,8 @@ public final class JSONFormat { wrapSingleColumnRecords, quoteNested, newNanAsString, - infinityAsString + infinityAsString, + binaryFormat ); } @@ -624,7 +643,8 @@ public final class JSONFormat { wrapSingleColumnRecords, quoteNested, nanAsString, - newInfinityAsString + newInfinityAsString, + binaryFormat ); } @@ -640,6 +660,42 @@ public final class JSONFormat { return infinityAsString; } + /** + * The {@link BinaryFormat} to use when formatting binary data. + */ + @NotNull + public final JSONFormat binaryFormat(BinaryFormat newBinaryFormat) { + if (mutable) { + binaryFormat = newBinaryFormat; + return this; + } + else + return new JSONFormat( + mutable, + format, + newline, + globalIndent, + indent, + indented, + header, + recordFormat, + objectNulls, + arrayNulls, + wrapSingleColumnRecords, + quoteNested, + nanAsString, + infinityAsString, + newBinaryFormat + ); + } + + /** + * The {@link BinaryFormat} to use when formatting binary data. + */ + public final BinaryFormat binaryFormat() { + return binaryFormat; + } + /** * The format of individual JSON records. */ @@ -682,4 +738,20 @@ public final class JSONFormat { */ ABSENT_ON_NULL, } + + /** + * The format of binary values in JSON documents. + */ + public enum BinaryFormat { + + /** + * Binary values are formatted as {@link Base64} encoded strings. + */ + BASE64, + + /** + * Binary values are formatted as {@link HexFormat} encoded strings. + */ + HEX + } } diff --git a/jOOQ/src/main/java/org/jooq/impl/AbstractResult.java b/jOOQ/src/main/java/org/jooq/impl/AbstractResult.java index 9d2af76556..d0dc313977 100644 --- a/jOOQ/src/main/java/org/jooq/impl/AbstractResult.java +++ b/jOOQ/src/main/java/org/jooq/impl/AbstractResult.java @@ -73,6 +73,7 @@ import javax.xml.parsers.ParserConfigurationException; import org.jooq.CSVFormat; import org.jooq.ChartFormat; import org.jooq.ChartFormat.Display; +import org.jooq.JSONFormat.BinaryFormat; import org.jooq.JSONFormat.NullFormat; import org.jooq.Configuration; import org.jooq.Constants; @@ -635,7 +636,11 @@ abstract class AbstractResult extends AbstractFormattable impl // [#2741] TODO: This logic will be externalised in new SPI if (value instanceof byte[] a) { - JSONValue.writeJSONString(Base64.getEncoder().encodeToString(a), writer); + if (format.binaryFormat() == BinaryFormat.HEX) + JSONValue.writeJSONString(Tools.convertBytesToHex(a), writer); + else + JSONValue.writeJSONString(Base64.getEncoder().encodeToString(a), writer); + } // [#6563] Arrays can be serialised natively in JSON diff --git a/jOOQ/src/main/java/org/jooq/impl/JSONReader.java b/jOOQ/src/main/java/org/jooq/impl/JSONReader.java index 7ab39cbba4..254a7ccb51 100644 --- a/jOOQ/src/main/java/org/jooq/impl/JSONReader.java +++ b/jOOQ/src/main/java/org/jooq/impl/JSONReader.java @@ -236,9 +236,9 @@ final class JSONReader { return result; } - private static final Set ENCODE_BINARY_AS_HEX = SQLDialect.supportedBy(H2, POSTGRES, SQLITE, TRINO, YUGABYTEDB); - private static final Set ENCODE_BINARY_AS_TEXT = SQLDialect.supportedBy(MARIADB); - private static final Pattern P_MYSQL_BINARY_PREFIX = Pattern.compile("^base64:type\\d+:(.*)$"); + static final Set ENCODE_BINARY_AS_HEX = SQLDialect.supportedBy(H2, POSTGRES, SQLITE, TRINO, YUGABYTEDB); + static final Set ENCODE_BINARY_AS_TEXT = SQLDialect.supportedBy(MARIADB); + private static final Pattern P_MYSQL_BINARY_PREFIX = Pattern.compile("^base64:type\\d+:(.*)$"); private static final List patchRecord( DSLContext ctx,