using System;
using System.IO;
using System.Linq;
using System.Text;
using Utf8Json.Internal;
using Utf8Json.Resolvers;
namespace Utf8Json
{
///
/// High-Level API of Utf8Json.
///
public static partial class JsonSerializer
{
static IJsonFormatterResolver defaultResolver;
///
/// FormatterResolver that used resolver less overloads. If does not set it, used StandardResolver.Default.
///
public static IJsonFormatterResolver DefaultResolver
{
get
{
if (defaultResolver == null)
{
defaultResolver = StandardResolver.Default;
}
return defaultResolver;
}
}
///
/// Is resolver decided?
///
public static bool IsInitialized
{
get
{
return defaultResolver != null;
}
}
///
/// Set default resolver of Utf8Json APIs.
///
///
public static void SetDefaultResolver(IJsonFormatterResolver resolver)
{
defaultResolver = resolver;
}
///
/// Serialize to binary with default resolver.
///
public static byte[] Serialize(T obj)
{
return Serialize(obj, defaultResolver);
}
///
/// Serialize to binary with specified resolver.
///
public static byte[] Serialize(T value, IJsonFormatterResolver resolver)
{
if (resolver == null) resolver = DefaultResolver;
var writer = new JsonWriter(MemoryPool.GetBuffer());
var formatter = resolver.GetFormatterWithVerify();
formatter.Serialize(ref writer, value, resolver);
return writer.ToUtf8ByteArray();
}
public static void Serialize(ref JsonWriter writer, T value)
{
Serialize(ref writer, value, defaultResolver);
}
public static void Serialize(ref JsonWriter writer, T value, IJsonFormatterResolver resolver)
{
if (resolver == null) resolver = DefaultResolver;
var formatter = resolver.GetFormatterWithVerify();
formatter.Serialize(ref writer, value, resolver);
}
///
/// Serialize to stream.
///
public static void Serialize(Stream stream, T value)
{
Serialize(stream, value, defaultResolver);
}
///
/// Serialize to stream with specified resolver.
///
public static void Serialize(Stream stream, T value, IJsonFormatterResolver resolver)
{
if (resolver == null) resolver = DefaultResolver;
var buffer = SerializeUnsafe(value, resolver);
stream.Write(buffer.Array, buffer.Offset, buffer.Count);
}
#if NETSTANDARD
///
/// Serialize to stream(write async).
///
public static System.Threading.Tasks.Task SerializeAsync(Stream stream, T value)
{
return SerializeAsync(stream, value, defaultResolver);
}
///
/// Serialize to stream(write async) with specified resolver.
///
public static async System.Threading.Tasks.Task SerializeAsync(Stream stream, T value, IJsonFormatterResolver resolver)
{
if (resolver == null) resolver = DefaultResolver;
var buf = BufferPool.Default.Rent();
try
{
var writer = new JsonWriter(buf);
var formatter = resolver.GetFormatterWithVerify();
formatter.Serialize(ref writer, value, resolver);
var buffer = writer.GetBuffer();
await stream.WriteAsync(buffer.Array, buffer.Offset, buffer.Count).ConfigureAwait(false);
}
finally
{
BufferPool.Default.Return(buf);
}
}
#endif
///
/// Serialize to binary. Get the raw memory pool byte[]. The result can not share across thread and can not hold, so use quickly.
///
public static ArraySegment SerializeUnsafe(T obj)
{
return SerializeUnsafe(obj, defaultResolver);
}
///
/// Serialize to binary with specified resolver. Get the raw memory pool byte[]. The result can not share across thread and can not hold, so use quickly.
///
public static ArraySegment SerializeUnsafe(T value, IJsonFormatterResolver resolver)
{
if (resolver == null) resolver = DefaultResolver;
var writer = new JsonWriter(MemoryPool.GetBuffer());
var formatter = resolver.GetFormatterWithVerify();
formatter.Serialize(ref writer, value, resolver);
return writer.GetBuffer();
}
///
/// Serialize to JsonString.
///
public static string ToJsonString(T value)
{
return ToJsonString(value, defaultResolver);
}
///
/// Serialize to JsonString with specified resolver.
///
public static string ToJsonString(T value, IJsonFormatterResolver resolver)
{
if (resolver == null) resolver = DefaultResolver;
var writer = new JsonWriter(MemoryPool.GetBuffer());
var formatter = resolver.GetFormatterWithVerify();
formatter.Serialize(ref writer, value, resolver);
return writer.ToString();
}
public static T Deserialize(string json)
{
return Deserialize(json, defaultResolver);
}
public static T Deserialize(string json, IJsonFormatterResolver resolver)
{
return Deserialize(StringEncoding.UTF8.GetBytes(json), resolver);
}
public static T Deserialize(byte[] bytes)
{
return Deserialize(bytes, defaultResolver);
}
public static T Deserialize(byte[] bytes, IJsonFormatterResolver resolver)
{
return Deserialize(bytes, 0, resolver);
}
public static T Deserialize(byte[] bytes, int offset)
{
return Deserialize(bytes, offset, defaultResolver);
}
public static T Deserialize(byte[] bytes, int offset, IJsonFormatterResolver resolver)
{
if (resolver == null) resolver = DefaultResolver;
var reader = new JsonReader(bytes, offset);
var formatter = resolver.GetFormatterWithVerify();
return formatter.Deserialize(ref reader, resolver);
}
public static T Deserialize(ref JsonReader reader)
{
return Deserialize(ref reader, defaultResolver);
}
public static T Deserialize(ref JsonReader reader, IJsonFormatterResolver resolver)
{
if (resolver == null) resolver = DefaultResolver;
var formatter = resolver.GetFormatterWithVerify();
return formatter.Deserialize(ref reader, resolver);
}
public static T Deserialize(Stream stream)
{
return Deserialize(stream, defaultResolver);
}
public static T Deserialize(Stream stream, IJsonFormatterResolver resolver)
{
if (resolver == null) resolver = DefaultResolver;
#if NETSTANDARD && !NET45
var ms = stream as MemoryStream;
if (ms != null)
{
ArraySegment buf2;
if (ms.TryGetBuffer(out buf2))
{
// when token is number, can not use from pool(can not find end line).
var token = new JsonReader(buf2.Array, buf2.Offset).GetCurrentJsonToken();
if (token == JsonToken.Number)
{
var buf3 = new byte[buf2.Count];
Buffer.BlockCopy(buf2.Array, buf2.Offset, buf3, 0, buf3.Length);
return Deserialize(buf3, 0, resolver);
}
return Deserialize(buf2.Array, buf2.Offset, resolver);
}
}
#endif
{
var buf = MemoryPool.GetBuffer();
var len = FillFromStream(stream, ref buf);
// when token is number, can not use from pool(can not find end line).
var token = new JsonReader(buf).GetCurrentJsonToken();
if (token == JsonToken.Number)
{
buf = BinaryUtil.FastCloneWithResize(buf, len);
}
return Deserialize(buf, resolver);
}
}
#if NETSTANDARD
public static System.Threading.Tasks.Task DeserializeAsync(Stream stream)
{
return DeserializeAsync(stream, defaultResolver);
}
public static async System.Threading.Tasks.Task DeserializeAsync(Stream stream, IJsonFormatterResolver resolver)
{
if (resolver == null) resolver = DefaultResolver;
var buffer = BufferPool.Default.Rent();
var buf = buffer;
try
{
int length = 0;
int read;
while ((read = await stream.ReadAsync(buf, length, buf.Length - length).ConfigureAwait(false)) > 0)
{
length += read;
if (length == buf.Length)
{
BinaryUtil.FastResize(ref buf, length * 2);
}
}
// when token is number, can not use from pool(can not find end line).
var token = new JsonReader(buf).GetCurrentJsonToken();
if (token == JsonToken.Number)
{
buf = BinaryUtil.FastCloneWithResize(buf, length);
}
return Deserialize(buf, resolver);
}
finally
{
BufferPool.Default.Return(buffer);
}
}
#endif
public static string PrettyPrint(byte[] json)
{
return PrettyPrint(json, 0);
}
public static string PrettyPrint(byte[] json, int offset)
{
var reader = new JsonReader(json, offset);
var writer = new JsonWriter(MemoryPool.GetBuffer());
WritePrittyPrint(ref reader, ref writer, 0);
return writer.ToString();
}
public static string PrettyPrint(string json)
{
var reader = new JsonReader(Encoding.UTF8.GetBytes(json));
var writer = new JsonWriter(MemoryPool.GetBuffer());
WritePrittyPrint(ref reader, ref writer, 0);
return writer.ToString();
}
public static byte[] PrettyPrintByteArray(byte[] json)
{
return PrettyPrintByteArray(json, 0);
}
public static byte[] PrettyPrintByteArray(byte[] json, int offset)
{
var reader = new JsonReader(json, offset);
var writer = new JsonWriter(MemoryPool.GetBuffer());
WritePrittyPrint(ref reader, ref writer, 0);
return writer.ToUtf8ByteArray();
}
public static byte[] PrettyPrintByteArray(string json)
{
var reader = new JsonReader(Encoding.UTF8.GetBytes(json));
var writer = new JsonWriter(MemoryPool.GetBuffer());
WritePrittyPrint(ref reader, ref writer, 0);
return writer.ToUtf8ByteArray();
}
static readonly byte[][] indent = Enumerable.Range(0, 100).Select(x => Encoding.UTF8.GetBytes(new string(' ', x * 2))).ToArray();
static readonly byte[] newLine = Encoding.UTF8.GetBytes(Environment.NewLine);
static void WritePrittyPrint(ref JsonReader reader, ref JsonWriter writer, int depth)
{
var token = reader.GetCurrentJsonToken();
switch (token)
{
case JsonToken.BeginObject:
{
writer.WriteBeginObject();
writer.WriteRaw(newLine);
var c = 0;
while (reader.ReadIsInObject(ref c))
{
if (c != 1)
{
writer.WriteRaw((byte)',');
writer.WriteRaw(newLine);
}
writer.WriteRaw(indent[depth + 1]);
writer.WritePropertyName(reader.ReadPropertyName());
writer.WriteRaw((byte)' ');
WritePrittyPrint(ref reader, ref writer, depth + 1);
}
writer.WriteRaw(newLine);
writer.WriteRaw(indent[depth]);
writer.WriteEndObject();
}
break;
case JsonToken.BeginArray:
{
writer.WriteBeginArray();
writer.WriteRaw(newLine);
var c = 0;
while (reader.ReadIsInArray(ref c))
{
if (c != 1)
{
writer.WriteRaw((byte)',');
writer.WriteRaw(newLine);
}
writer.WriteRaw(indent[depth + 1]);
WritePrittyPrint(ref reader, ref writer, depth + 1);
}
writer.WriteRaw(newLine);
writer.WriteRaw(indent[depth]);
writer.WriteEndArray();
}
break;
case JsonToken.Number:
{
var v = reader.ReadDouble();
writer.WriteDouble(v);
}
break;
case JsonToken.String:
{
var v = reader.ReadString();
writer.WriteString(v);
}
break;
case JsonToken.True:
case JsonToken.False:
{
var v = reader.ReadBoolean();
writer.WriteBoolean(v);
}
break;
case JsonToken.Null:
{
reader.ReadIsNull();
writer.WriteNull();
}
break;
default:
break;
}
}
static int FillFromStream(Stream input, ref byte[] buffer)
{
int length = 0;
int read;
while ((read = input.Read(buffer, length, buffer.Length - length)) > 0)
{
length += read;
if (length == buffer.Length)
{
BinaryUtil.FastResize(ref buffer, length * 2);
}
}
return length;
}
static class MemoryPool
{
[ThreadStatic]
static byte[] buffer = null;
public static byte[] GetBuffer()
{
if (buffer == null)
{
buffer = new byte[65536];
}
return buffer;
}
}
}
}