139 lines
4.4 KiB
C#
139 lines
4.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using LeanCloud.Utilities;
|
|
using LeanCloud.Storage.Internal;
|
|
|
|
namespace LeanCloud.Storage.Internal
|
|
{
|
|
/// <summary>
|
|
/// A <c>AVEncoder</c> can be used to transform objects such as <see cref="AVObject"/> into JSON
|
|
/// data structures.
|
|
/// </summary>
|
|
/// <seealso cref="AVDecoder"/>
|
|
public abstract class AVEncoder
|
|
{
|
|
#if UNITY
|
|
private static readonly bool isCompiledByIL2CPP = AppDomain.CurrentDomain.FriendlyName.Equals("IL2CPP Root Domain");
|
|
#else
|
|
private static readonly bool isCompiledByIL2CPP = false;
|
|
#endif
|
|
|
|
public static bool IsValidType(object value)
|
|
{
|
|
return value == null ||
|
|
ReflectionHelpers.IsPrimitive(value.GetType()) ||
|
|
value is string ||
|
|
value is AVObject ||
|
|
value is AVACL ||
|
|
value is AVFile ||
|
|
value is AVGeoPoint ||
|
|
value is AVRelationBase ||
|
|
value is DateTime ||
|
|
value is byte[] ||
|
|
Conversion.As<IDictionary<string, object>>(value) != null ||
|
|
Conversion.As<IList<object>>(value) != null;
|
|
}
|
|
|
|
public object Encode(object value)
|
|
{
|
|
// If this object has a special encoding, encode it and return the
|
|
// encoded object. Otherwise, just return the original object.
|
|
if (value is DateTime)
|
|
{
|
|
return new Dictionary<string, object>
|
|
{
|
|
{
|
|
"iso", ((DateTime)value).ToUniversalTime().ToString(AVClient.DateFormatStrings.First(), CultureInfo.InvariantCulture)
|
|
},
|
|
{
|
|
"__type", "Date"
|
|
}
|
|
};
|
|
}
|
|
|
|
if (value is AVFile)
|
|
{
|
|
var file = value as AVFile;
|
|
return new Dictionary<string, object>
|
|
{
|
|
{"__type", "Pointer"},
|
|
{ "className", "_File"},
|
|
{ "objectId", file.ObjectId}
|
|
};
|
|
}
|
|
|
|
var bytes = value as byte[];
|
|
if (bytes != null)
|
|
{
|
|
return new Dictionary<string, object>
|
|
{
|
|
{ "__type", "Bytes"},
|
|
{ "base64", Convert.ToBase64String(bytes)}
|
|
};
|
|
}
|
|
|
|
var obj = value as AVObject;
|
|
if (obj != null)
|
|
{
|
|
return EncodeAVObject(obj);
|
|
}
|
|
|
|
var jsonConvertible = value as IJsonConvertible;
|
|
if (jsonConvertible != null)
|
|
{
|
|
return jsonConvertible.ToJSON();
|
|
}
|
|
|
|
var dict = Conversion.As<IDictionary<string, object>>(value);
|
|
if (dict != null)
|
|
{
|
|
var json = new Dictionary<string, object>();
|
|
foreach (var pair in dict)
|
|
{
|
|
json[pair.Key] = Encode(pair.Value);
|
|
}
|
|
return json;
|
|
}
|
|
|
|
var list = Conversion.As<IList<object>>(value);
|
|
if (list != null)
|
|
{
|
|
return EncodeList(list);
|
|
}
|
|
|
|
// TODO (hallucinogen): convert IAVFieldOperation to IJsonConvertible
|
|
var operation = value as IAVFieldOperation;
|
|
if (operation != null)
|
|
{
|
|
return operation.Encode();
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
protected abstract IDictionary<string, object> EncodeAVObject(AVObject value);
|
|
|
|
private object EncodeList(IList<object> list)
|
|
{
|
|
var newArray = new List<object>();
|
|
// We need to explicitly cast `list` to `List<object>` rather than
|
|
// `IList<object>` because IL2CPP is stricter than the usual Unity AOT compiler pipeline.
|
|
if (isCompiledByIL2CPP && list.GetType().IsArray)
|
|
{
|
|
list = new List<object>(list);
|
|
}
|
|
foreach (var item in list)
|
|
{
|
|
if (!IsValidType(item))
|
|
{
|
|
throw new ArgumentException("Invalid type for value in an array");
|
|
}
|
|
newArray.Add(Encode(item));
|
|
}
|
|
return newArray;
|
|
}
|
|
}
|
|
}
|