Files
back_cantanBuilding/LocalPackages/rtm-sdk-unity-2.7.20/Runtime/Plugins/fpnn/common/JsonStringify.cs
2026-05-26 16:15:54 +08:00

323 lines
9.3 KiB
C#

using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;
namespace com.fpnn.common
{
internal static class JsonStringEscaper
{
public delegate void CharEscape(StringBuilder sb, char c);
private static readonly Dictionary<char, CharEscape> _charEscapeDict;
static JsonStringEscaper()
{
_charEscapeDict = new Dictionary<char, CharEscape>
{
{ '\\', Slash },
{ '"', QuotationMarks },
{ '\b', SpecialChars },
{ '\f', SpecialChars },
{ '\n', SpecialChars },
{ '\r', SpecialChars },
{ '\t', SpecialChars },
};
}
static public void Escape(StringBuilder sb, string str)
{
for (int i = 0; i < str.Length; i++)
{
char c = str[i];
if (_charEscapeDict.TryGetValue(c, out CharEscape escapeFunc))
{
escapeFunc(sb, c);
}
else
{
ushort value = Convert.ToUInt16(c);
if (value > 0x1f && value < 0x7f) //-- ASCII visible chars
{
sb.Append(c);
}
else
{
sb.Append("\\u");
sb.Append(value.ToString("x4"));
}
}
}
}
static private void SpecialChars(StringBuilder sb, char c)
{
switch (c)
{
case '\b': sb.Append("\\b"); break;
case '\f': sb.Append("\\f"); break;
case '\n': sb.Append("\\n"); break;
case '\r': sb.Append("\\r"); break;
case '\t': sb.Append("\\t"); break;
}
}
static private void Slash(StringBuilder sb, char c)
{
sb.Append("\\\\");
}
static private void QuotationMarks(StringBuilder sb, char c)
{
sb.Append("\\\"");
}
}
//============================[ Exception ]============================//
public class UnsupportedTypeException : JsonException
{
public UnsupportedTypeException(string message) : base(message) { }
static public UnsupportedTypeException Create(Object obj)
{
string typeFullName = obj.GetType().FullName;
return new UnsupportedTypeException("FPJson unsupported type: " + typeFullName);
}
static public UnsupportedTypeException DictionaryKey(Object obj)
{
string typeFullName = obj.GetType().FullName;
return new UnsupportedTypeException("FPJson unsupported object key type: " + typeFullName);
}
}
//============================[ Json Stringify ]============================//
internal class JsonStringify
{
public delegate void Serialize(JsonStringify js, object obj);
private static readonly Dictionary<string, Serialize> _serializeDict;
static JsonStringify()
{
_serializeDict = new Dictionary<string, Serialize>
{
{ "System.Boolean", SerializeBoolean },
{ "System.Decimal", SerializeDecimal },
{ "System.Double", SerializeDouble },
{ "System.Single", SerializeFloat },
{ "System.SByte", SerializeInteger },
{ "System.Int16", SerializeInteger },
{ "System.Int32", SerializeInteger },
{ "System.Int64", SerializeInteger },
{ "System.Byte", SerializeUInteger },
{ "System.Char", SerializeUInteger },
{ "System.UInt16", SerializeUInteger },
{ "System.UInt32", SerializeUInteger },
{ "System.UInt64", SerializeUInteger },
{ "System.String", SerializeString },
{ "System.Tuple", SerializeTuple },
{ "System.DateTime", SerializeTimestamp }
};
}
//-- Instance Methods
private StringBuilder sb;
public JsonStringify()
{
sb = new StringBuilder();
}
public string Stringify(object obj)
{
if (obj == null)
{
SerializeNull(this);
return sb.ToString();
}
string typeFullName = obj.GetType().FullName;
int idx = typeFullName.IndexOf('`');
if (idx != -1)
{
typeFullName = typeFullName.Substring(0, idx);
}
if (_serializeDict.TryGetValue(typeFullName, out Serialize serializer))
{
serializer(this, obj);
}
else if (obj is IEnumerable)
{
SerializeIEnumerable(this, obj);
}
else
{
throw UnsupportedTypeException.Create(obj);
}
return sb.ToString();
}
static private void SerializeBoolean(JsonStringify js, object obj)
{
Boolean v = (bool)obj;
if (v == true)
js.sb.Append("true");
else
js.sb.Append("false");
}
static private void SerializeDecimal(JsonStringify js, object obj)
{
Decimal dec = (Decimal)obj;
js.sb.Append(dec);
}
static private void SerializeDouble(JsonStringify js, object obj)
{
double value = (double)obj;
js.sb.Append(value);
}
static private void SerializeFloat(JsonStringify js, object obj)
{
float value = (float)obj;
js.sb.Append(value);
}
static private void SerializeInteger(JsonStringify js, object obj)
{
Int64 value = (Int64)Convert.ChangeType(obj, TypeCode.Int64);
js.sb.Append(value);
}
static private void SerializeUInteger(JsonStringify js, object obj)
{
UInt64 value = (UInt64)Convert.ChangeType(obj, TypeCode.UInt64);
js.sb.Append(value);
}
static private void SerializeString(JsonStringify js, object obj)
{
string str = (string)obj;
js.sb.Append("\"");
JsonStringEscaper.Escape(js.sb, str);
js.sb.Append("\"");
}
static private void SerializeTuple(JsonStringify js, object obj)
{
Type objType = obj.GetType();
var props = objType.GetProperties();
bool isFirst = true;
js.sb.Append("[");
foreach (System.Reflection.PropertyInfo prop in props)
{
if (isFirst)
isFirst = false;
else
js.sb.Append(",");
object o = prop.GetValue(obj, null);
js.Stringify(o);
}
js.sb.Append("]");
}
static private void SerializeTimestamp(JsonStringify js, object obj)
{
DateTime userDate = (DateTime)obj;
var univDateTime = userDate.ToUniversalTime();
js.sb.Append("\"");
js.sb.Append(univDateTime.ToString("yyyy-MM-dd HH:mm:ss"));
js.sb.Append("\"");
}
static private void SerializeNull(JsonStringify js)
{
js.sb.Append("null");
}
static private void SerializeArray(JsonStringify js, object obj)
{
IEnumerable ie = (IEnumerable)obj;
IEnumerator it = ie.GetEnumerator();
it.Reset();
bool isFirst = true;
js.sb.Append("[");
while (it.MoveNext())
{
if (isFirst)
isFirst = false;
else
js.sb.Append(",");
object o = it.Current;
js.Stringify(o);
}
js.sb.Append("]");
}
static private void SerializeDictionary(JsonStringify js, object obj)
{
IEnumerable ie = (IEnumerable)obj;
IEnumerator it = ie.GetEnumerator();
it.Reset();
bool isFirst = true;
js.sb.Append("{");
IDictionaryEnumerator id = (IDictionaryEnumerator)it;
while (it.MoveNext())
{
if (isFirst)
isFirst = false;
else
js.sb.Append(",");
object k = id.Key;
if (Type.GetTypeCode(k.GetType()) != TypeCode.String)
throw UnsupportedTypeException.DictionaryKey(k);
js.Stringify(k);
js.sb.Append(":");
object v = id.Value;
js.Stringify(v);
}
js.sb.Append("}");
}
static private void SerializeIEnumerable(JsonStringify js, object obj)
{
IEnumerable ie = (IEnumerable)obj;
IEnumerator it = ie.GetEnumerator();
it.Reset();
if (it is IDictionaryEnumerator)
SerializeDictionary(js, obj);
else
SerializeArray(js, obj);
}
}
}