/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
using Carbon.Json;
using System;
namespace Microsoft.Rest.ClientRuntime
{
public interface IJsonSerializable
{
JsonNode ToJson(JsonObject container = null, SerializationMode serializationMode = SerializationMode.None);
}
internal static class JsonSerializable
{
///
/// Serializes an enumerable and returns a JsonNode.
///
/// an IEnumerable collection of items
/// A JsonNode that contains the collection of items serialized.
private static JsonNode ToJsonValue(System.Collections.IEnumerable enumerable)
{
if (enumerable != null)
{
// is it a byte array of some kind?
if (enumerable is System.Collections.Generic.IEnumerable byteEnumerable)
{
return new XBinary(System.Linq.Enumerable.ToArray(byteEnumerable));
}
var hasValues = false;
// just create an array of value nodes.
var result = new XNodeArray();
foreach (var each in enumerable)
{
// we had at least one value.
hasValues = true;
// try to serialize it.
var node = ToJsonValue(each);
if (null != node)
{
result.Add(node);
}
}
// if we were able to add values, (or it was just empty), return it.
if (result.Count > 0 || !hasValues)
{
return result;
}
}
// we couldn't serialize the values. Sorry.
return null;
}
///
/// Serializes a valuetype to a JsonNode.
///
/// a ValueType (ie, a primitive, enum or struct) to be serialized
/// a JsonNode with the serialized value
private static JsonNode ToJsonValue(ValueType vValue)
{
// numeric type
if (vValue is SByte || vValue is Int16 || vValue is Int32 || vValue is Int64 || vValue is Byte || vValue is UInt16 || vValue is UInt32 || vValue is UInt64 || vValue is decimal || vValue is float || vValue is double)
{
return new JsonNumber(vValue.ToString());
}
// boolean type
if (vValue is bool bValue)
{
return new JsonBoolean(bValue);
}
// dates
if (vValue is DateTime dtValue)
{
return new JsonDate(dtValue);
}
// DictionaryEntity struct type
if (vValue is System.Collections.DictionaryEntry deValue)
{
return new JsonObject { { deValue.Key.ToString(), ToJsonValue(deValue.Value) } };
}
// sorry, no idea.
return null;
}
///
/// Attempts to serialize an object by using ToJson() or ToJsonString() if they exist.
///
/// the object to be serialized.
/// the serialized JsonNode (if successful), otherwise, null
private static JsonNode TryToJsonValue(dynamic oValue)
{
object jsonValue = null;
dynamic v = oValue;
try
{
jsonValue = v.ToJson().ToString();
}
catch
{
// no harm...
try
{
jsonValue = v.ToJsonString().ToString();
}
catch
{
// no worries here either.
}
}
// if we got something out, let's use it.
if (null != jsonValue)
{
// JsonNumber is really a literal json value. Just don't try to cast that back to an actual number, ok?
return new JsonNumber(jsonValue.ToString());
}
return null;
}
///
/// Serialize an object by using a variety of methods.
///
/// the object to be serialized.
/// the serialized JsonNode (if successful), otherwise, null
internal static JsonNode ToJsonValue(object value)
{
// things that implement our interface are preferred.
if (value is Microsoft.Rest.ClientRuntime.IJsonSerializable jsonSerializable)
{
return jsonSerializable.ToJson();
}
// strings are easy.
if (value is string || value is char)
{
return new JsonString(value.ToString());
}
// value types are fairly straightforward (fallback to ToJson()/ToJsonString() or literal JsonString )
if (value is System.ValueType vValue)
{
return ToJsonValue(vValue) ?? TryToJsonValue(vValue) ?? new JsonString(vValue.ToString());
}
// dictionaries are objects that should be able to serialize
if (value is System.Collections.Generic.IDictionary dictionary)
{
return Microsoft.Rest.ClientRuntime.JsonSerializable.ToJson(dictionary, null);
}
// hashtables are converted to dictionaries for serialization
if (value is System.Collections.Hashtable hashtable)
{
var dict = new System.Collections.Generic.Dictionary();
DictionaryExtensions.HashTableToDictionary