diff --git a/sdk/core/azure-core-experimental/CHANGELOG.md b/sdk/core/azure-core-experimental/CHANGELOG.md index 369cd8bcefe5..9ed249c7810f 100644 --- a/sdk/core/azure-core-experimental/CHANGELOG.md +++ b/sdk/core/azure-core-experimental/CHANGELOG.md @@ -2,6 +2,7 @@ ## 1.0.0-beta.7 (2020-10-08) +- Added API `fromObject()` in `BinaryData` which uses `JsonSerializer` present in the classpath. - Added APIs to `JsonPatchDocument` which accept pre-serialized JSON. - Updated `azure-core` dependency to released version. diff --git a/sdk/core/azure-core-experimental/src/main/java/com/azure/core/experimental/util/BinaryData.java b/sdk/core/azure-core-experimental/src/main/java/com/azure/core/experimental/util/BinaryData.java index 2979599d21ca..060cda67f27b 100644 --- a/sdk/core/azure-core-experimental/src/main/java/com/azure/core/experimental/util/BinaryData.java +++ b/sdk/core/azure-core-experimental/src/main/java/com/azure/core/experimental/util/BinaryData.java @@ -5,7 +5,9 @@ import com.azure.core.util.FluxUtil; import com.azure.core.util.logging.ClientLogger; +import com.azure.core.util.serializer.JsonSerializerProviders; import com.azure.core.util.serializer.ObjectSerializer; +import com.azure.core.util.serializer.JsonSerializer; import com.azure.core.util.serializer.TypeReference; import static com.azure.core.util.FluxUtil.monoError; @@ -18,18 +20,20 @@ import java.io.InputStream; import java.io.UncheckedIOException; import java.nio.ByteBuffer; -import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Objects; /** * This class is an abstraction over many different ways that binary data can be represented. The {@link BinaryData} - * can be created from {@link InputStream}, {@link Flux} of {@link ByteBuffer}, {@link String}, {@link Object} and byte - * array. The data is collected from provided sources and stored into a byte array. + * can be created from {@link InputStream}, {@link Flux} of {@link ByteBuffer}, {@link String}, {@link Object}, or byte + * array. + *
Immutable data
+ * {@link BinaryData} is constructed by copying the given data. Once {@link BinaryData} is instantiated, it can not be + * changed. It provides various convenient APIs to get data out of {@link BinaryData}, they all start with the 'to' + * prefix, for example {@link BinaryData#toBytes()}. *- * It also provides a way to serialize and deserialize an {@link Object} into {@link BinaryData} given an - * {@link ObjectSerializer}. Code samples are explained below. + * Code samples are presented below. * *
Create an instance from Bytes
* {@codesnippet com.azure.core.experimental.util.BinaryDocument.from#bytes} @@ -43,57 +47,48 @@ *Get an Object from {@link BinaryData}
* {@codesnippet com.azure.core.experimental.util.BinaryDocument.to#ObjectAsync} * + *Create an instance from Object
+ * {@codesnippet com.azure.core.experimental.util.BinaryDocument.from#Object} + * * @see ObjectSerializer + * @see JsonSerializer + * @see More about serialization */ public final class BinaryData { private static final ClientLogger LOGGER = new ClientLogger(BinaryData.class); - private final byte[] data; + private static final BinaryData EMPTY_DATA = new BinaryData(new byte[0]); - /** - * Create instance of {@link BinaryData} given the data. - * @param data to represent as bytes. - * @throws NullPointerException If {@code data} is null. - */ - BinaryData(byte[] data) { - Objects.requireNonNull(data, "'data' cannot be null."); - this.data = Arrays.copyOf(data, data.length); - } + private static final Object LOCK = new Object(); - /** - * Provides {@link InputStream} for the data represented by this {@link BinaryData} object. - * - *Get InputStream from BinaryData
- * {@codesnippet com.azure.core.experimental.util.BinaryDocument.to#Stream} - * - * @return {@link InputStream} representing the binary data. - */ - public InputStream toStream() { - return new ByteArrayInputStream(this.data); - } + private final byte[] data; + + private static volatile JsonSerializer defaultJsonSerializer; /** - * Provides {@link Mono} of {@link InputStream} for the data represented by this {@link BinaryData} object. + * Create an instance of {@link BinaryData} from the given data. * - * @return {@link InputStream} representation of the {@link BinaryData}. + * @param data to represent as bytes. */ - public MonoCreate an instance from InputStream
* {@codesnippet com.azure.core.experimental.util.BinaryDocument.from#Stream} * * @param inputStream to read bytes from. * @throws UncheckedIOException If any error in reading from {@link InputStream}. - * @throws NullPointerException if {@code inputStream} is null. + * @throws NullPointerException If {@code inputStream} is null. * @return {@link BinaryData} representing the binary data. */ public static BinaryData fromStream(InputStream inputStream) { - Objects.requireNonNull(inputStream, "'inputStream' cannot be null."); + if (Objects.isNull(inputStream)) { + return EMPTY_DATA; + } final int bufferSize = 1024; try { @@ -103,98 +98,125 @@ public static BinaryData fromStream(InputStream inputStream) { while ((nRead = inputStream.read(data, 0, data.length)) != -1) { dataOutputBuffer.write(data, 0, nRead); } + dataOutputBuffer.flush(); + + return new BinaryData(dataOutputBuffer.toByteArray()); - return fromBytes(dataOutputBuffer.toByteArray()); } catch (IOException ex) { throw LOGGER.logExceptionAsError(new UncheckedIOException(ex)); } } /** - * Asynchronously create {@link BinaryData} instance with given {@link InputStream} as source of data. The - * {@link InputStream} is not closed by this function. + * Asynchronously creates a {@link BinaryData} instance with the given {@link InputStream} as source of data. The + * {@link InputStream} is not closed by this function. If the {@link InputStream} is {@code null}, an empty + * {@link BinaryData} will be returned. * * @param inputStream to read bytes from. - * @throws NullPointerException if {@code inputStream} is null. * @return {@link Mono} of {@link BinaryData} representing the binary data. */ public static MonoCreate an instance from String
* {@codesnippet com.azure.core.experimental.util.BinaryDocument.from#Flux} * * @param data to use. - * @throws NullPointerException if {@code inputStream} is null. * @return {@link Mono} of {@link BinaryData} representing binary data. */ public static MonoCreate an instance from String
- * {@codesnippet com.azure.core.experimental.util.BinaryDocument.from#String} + * Creates a {@link BinaryData} instance with given data. The {@link String} is converted into bytes using UTF_8 + * character set. If the String is {@code null}, an empty {@link BinaryData} will be returned. * * @param data to use. - * @param charSet to use. - * @throws NullPointerException if {@code inputStream} is null. - * @return {@link BinaryData} representing the binary data. + * @return {@link BinaryData} representing binary data. */ - public static BinaryData fromString(String data, Charset charSet) { - Objects.requireNonNull(data, "'data' cannot be null."); + public static BinaryData fromString(String data) { + if (Objects.isNull(data) || data.length() == 0) { + return EMPTY_DATA; + } - return new BinaryData(data.getBytes(charSet)); + return new BinaryData(data.getBytes(StandardCharsets.UTF_8)); } /** - * Create {@link BinaryData} instance with given data. The {@link String} is converted into bytes using - * {@link StandardCharsets#UTF_8} character set. + * Creates a {@link BinaryData} instance with given byte array data. If the byte array is {@code null}, an empty + * {@link BinaryData} will be returned. * * @param data to use. - * @throws NullPointerException if {@code inputStream} is null. - * @return {@link BinaryData} representing binary data. + * @return {@link BinaryData} representing the binary data. */ - public static BinaryData fromString(String data) { - Objects.requireNonNull(data, "'data' cannot be null."); + public static BinaryData fromBytes(byte[] data) { + if (Objects.isNull(data) || data.length == 0) { + return EMPTY_DATA; + } - return new BinaryData(data.getBytes(StandardCharsets.UTF_8)); + return new BinaryData(Arrays.copyOf(data, data.length)); } /** - * Create {@link BinaryData} instance with given byte array data. + * Serialize the given {@link Object} into {@link BinaryData} using json serializer which is available on classpath. + * The serializer on classpath must implement {@link JsonSerializer} interface. If the given Object is {@code null}, + * an empty {@link BinaryData} will be returned. + *Code sample
+ * {@codesnippet com.azure.core.experimental.util.BinaryDocument.from.default.serializer#Object} + + * @param data The {@link Object} which needs to be serialized into bytes. + * @throws IllegalStateException If a {@link JsonSerializer} cannot be found on the classpath. + * @return {@link BinaryData} representing the JSON serialized object. * - * @param data to use. - * @return {@link BinaryData} representing the binary data. + * @see JsonSerializer + * @see More about serialization */ - public static BinaryData fromBytes(byte[] data) { - return new BinaryData(data); + public static BinaryData fromObject(Object data) { + if (Objects.isNull(data)) { + return EMPTY_DATA; + } + final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + getDefaultSerializer().serialize(outputStream, data); + + return new BinaryData(outputStream.toByteArray()); } /** * Serialize the given {@link Object} into {@link BinaryData} using the provided {@link ObjectSerializer}. + * If the Object is {@code null}, an empty {@link BinaryData} will be returned. + *You can provide your custom implementation of {@link ObjectSerializer} interface or use one provided in azure + * sdk by adding them as dependency. These implementations could be found at + * Json Jackson serializer + * and Gson based serializer. + * + *
Create an instance from Object
+ * {@codesnippet com.azure.core.experimental.util.BinaryDocument.from#Object} * * @param data The {@link Object} which needs to be serialized into bytes. * @param serializer to use for serializing the object. - * @throws NullPointerException if {@code inputStream} or {@code serializer} is null. + * @throws NullPointerException If {@code serializer} is null. * @return {@link BinaryData} representing binary data. + * @see ObjectSerializer + * @see JsonSerializer + * @see More about serialization */ public static BinaryData fromObject(Object data, ObjectSerializer serializer) { - Objects.requireNonNull(data, "'data' cannot be null."); + if (Objects.isNull(data)) { + return EMPTY_DATA; + } + Objects.requireNonNull(serializer, "'serializer' cannot be null."); final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); @@ -204,19 +226,25 @@ public static BinaryData fromObject(Object data, ObjectSerializer serializer) { /** * Serialize the given {@link Object} into {@link Mono} {@link BinaryData} using the provided - * {@link ObjectSerializer}. + * {@link ObjectSerializer}. If the Object is {@code null}, an empty {@link BinaryData} will be returned. + * + *You can provide your custom implementation of {@link ObjectSerializer} interface or use one provided in azure
+ * sdk by adding them as dependency. These implementations could be found at
+ * Json Jackson serializer
+ * and Gson based serializer.
*
* @param data The {@link Object} which needs to be serialized into bytes.
* @param serializer to use for serializing the object.
- * @throws NullPointerException if {@code inputStream} or {@code serializer} is null.
+ * @throws NullPointerException If {@code serializer} is null.
* @return {@link Mono} of {@link BinaryData} representing the binary data.
+ * @see ObjectSerializer
+ * @see More about serialization
*/
public static Mono You can provide your custom implementation of {@link ObjectSerializer} interface or use one provided in azure
+ * sdk by adding them as dependency. These implementations could be found at
+ * Json Jackson serializer
+ * and Gson based serializer.
+ *
+ * Code sample You can provide your custom implementation of {@link ObjectSerializer} interface or use one provided in azure
+ * sdk by adding them as dependency. These implementations could be found at
+ * Json Jackson serializer
+ * and Gson based serializer.
*
* Gets the specified object Gets the specified object Get InputStream from BinaryData