JD2022-TU1/main/tools/framework/JD.Serialization/Serializers/Json/JsonSerializer.cs

203 lines
6.2 KiB
C#

using System;
using System.Drawing;
using System.IO;
using System.Text;
namespace JD.Serialization
{
/// <summary>
/// Writes to Json format.
/// </summary>
/// <remarks>Reading is not supported yet!</remarks>
public class JsonSerializer : Serializer
{
public JsonSerializer()
: base(JD.Serialization.TypeMap.Instance)
{ }
protected override object LoadObjectFromFileImplementation(string file, Type type)
{
throw new NotImplementedException();
}
protected override bool SaveObjectToFileImplementation(object obj, string file)
{
throw new NotImplementedException();
}
/// <summary>
/// Saves the content of the object and returns it as a Json string.
/// </summary>
public string Serialize(object toSerialize)
{
var stringWriter = new StringWriter();
using (var writer = new JsonWriter(stringWriter))
{
WriteClass(writer, toSerialize);
}
return stringWriter.ToString();
}
public void Deserialize(string content, object toRead)
{
throw new NotImplementedException();
}
#region Implementation
private void WriteClass(JsonWriter writer, object instance)
{
if (instance == null)
{
return;
}
using (writer.Indent())
{
string typeName = FormatTypeName(instance.GetType());
WriteProperty(writer, "__class", typeName);
foreach (var field in SerializableFields(instance.GetType()))
{
var isDefaultValue = instance.HasDefaultValue(field);
if (isDefaultValue && writer.CommentDefaultValues)
{
writer.CommentCount++;
}
else if (isDefaultValue && writer.IgnoreDefaultValues)
{
continue;
}
WriteProperty(writer, FormatPropertyName(field), field.GetValue(instance, null));
if (isDefaultValue && writer.CommentDefaultValues)
{
writer.CommentCount--;
}
}
}
}
private void WriteProperty(JsonWriter writer, string propertyName, object propertyValue)
{
if (propertyValue == null)
return;
var valueType = propertyValue.GetType();
if (BasicTypeList.IsBasicType(valueType))
{
// Adds comment for enumerations to describe the effective value.
var comment = string.Empty;
if (valueType.IsEnum)
{
comment = $" /*{propertyValue}*/";
}
writer.WriteLine("{0}:{1}{2},", FormatPropertyName(propertyName), ConvertBaseTypeToJsonString(propertyValue), comment);
}
else if (IsCollection(valueType))
{
if (((IUAFCollection)propertyValue).Count > 0)
{
writer.WriteLine("{0}:", FormatPropertyName(propertyName));
WriteCollection(writer, (IUAFCollection)propertyValue);
}
}
else
{
writer.WriteLine("{0}:", FormatPropertyName(propertyName));
WriteClass(writer, propertyValue);
}
}
/// <summary>
/// Engine serializes the property with a lower case as its first character.
/// </summary>
private string FormatPropertyName(string propertyName)
{
var result = new StringBuilder(propertyName);
result[0] = char.ToLower(result[0]);
return Quote(result.ToString());
}
private void WriteCollection(JsonWriter writer, IUAFCollection collection)
{
using ( collection is IUAFList ? writer.IndentArrayBlock() : writer.Indent())
{
if (BasicTypeList.IsBasicType(collection.ElementType))
{
foreach (var item in collection.SerializableElements)
{
writer.WriteLine("{0},", ConvertBaseTypeToJsonString(item));
}
}
else if (collection is IUAFDictionary)
{
foreach (ISerializableKeyValuePair pair in collection.SerializableElements)
{
WriteProperty(writer, pair.Key.ToString(), pair.Value);
}
}
else
{
foreach (var item in collection.SerializableElements)
{
WriteClass(writer, item);
}
}
}
}
private string ConvertBaseTypeToJsonString(object obj)
{
if (obj.GetType().IsEnum)
{
return (Convert.ToInt32(obj)).ToString();
}
if (obj is float)
{
return ((double)(float)obj).ToString("0.000000");
}
if (obj is double)
{
return ((double)obj).ToString("0.000000");
}
switch (obj.GetType().Name)
{
case "String":
case "String8":
case "StringID":
case "ObjectPath":
case "Path":
case "Platform":
return $"\"{(obj.ToString() ?? "").Replace("\"", "\\\"")}\"";
case "Color":
return $"\"0x{((Color) obj).ToArgb():X8}\"";
case "Angle":
return $"{((Angle) obj).ToDegree()}";
case "Boolean":
return obj.ToString().ToLower();
}
return obj.ToString();
}
private string Quote(string value)
{
const string quote = "\"";
return string.Concat(quote, value, quote);
}
#endregion
}
}