forked from ln-dotnet/ln.json
194 lines
7.2 KiB
C#
194 lines
7.2 KiB
C#
// /**
|
|
// * File: JSONMapper.cs
|
|
// * Author: haraldwolff
|
|
// *
|
|
// * This file and it's content is copyrighted by the Author and / or copyright holder.
|
|
// * Any use wihtout proper permission is illegal and may lead to legal actions.
|
|
// *
|
|
// *
|
|
// **/
|
|
using System;
|
|
using System.Reflection;
|
|
using System.Collections.Generic;
|
|
using System.Collections;
|
|
using System.Diagnostics.Tracing;
|
|
namespace ln.json.mapping
|
|
{
|
|
public class JSONMapper
|
|
{
|
|
public static JSONMapper DefaultMapper { get; set; } = new JSONMapper(true);
|
|
|
|
Dictionary<Type, JSONMapping> mappings = new Dictionary<Type, JSONMapping>();
|
|
|
|
public JSONMapper()
|
|
{
|
|
}
|
|
private JSONMapper(bool defaultMapper)
|
|
{
|
|
/**
|
|
* Integer
|
|
**/
|
|
Add(new JSONMapping(
|
|
typeof(byte),
|
|
(JSONMapper arg1, object arg2) => new JSONNumber((int)arg2),
|
|
(JSONMapper arg1, JSONValue arg2) => Decimal.ToByte(((JSONNumber)arg2).Decimal)
|
|
));
|
|
Add(new JSONMapping(
|
|
typeof(short),
|
|
(JSONMapper arg1, object arg2) => new JSONNumber((int)arg2),
|
|
(JSONMapper arg1, JSONValue arg2) => Decimal.ToInt16(((JSONNumber)arg2).Decimal)
|
|
));
|
|
Add(new JSONMapping(
|
|
typeof(int),
|
|
(JSONMapper arg1, object arg2) => new JSONNumber((int)arg2),
|
|
(JSONMapper arg1, JSONValue arg2) => Decimal.ToInt32(((JSONNumber)arg2).Decimal)
|
|
));
|
|
Add(new JSONMapping(
|
|
typeof(long),
|
|
(JSONMapper arg1, object arg2) => new JSONNumber((long)arg2),
|
|
(JSONMapper arg1, JSONValue arg2) => Decimal.ToInt64(((JSONNumber)arg2).Decimal)
|
|
));
|
|
Add(new JSONMapping(
|
|
typeof(ushort),
|
|
(JSONMapper arg1, object arg2) => new JSONNumber((uint)arg2),
|
|
(JSONMapper arg1, JSONValue arg2) => Decimal.ToUInt16(((JSONNumber)arg2).Decimal)
|
|
));
|
|
Add(new JSONMapping(
|
|
typeof(uint),
|
|
(JSONMapper arg1, object arg2) => new JSONNumber((uint)arg2),
|
|
(JSONMapper arg1, JSONValue arg2) => Decimal.ToUInt32(((JSONNumber)arg2).Decimal)
|
|
));
|
|
Add(new JSONMapping(
|
|
typeof(ulong),
|
|
(JSONMapper arg1, object arg2) => new JSONNumber((ulong)arg2),
|
|
(JSONMapper arg1, JSONValue arg2) => Decimal.ToUInt64(((JSONNumber)arg2).Decimal)
|
|
));
|
|
|
|
/**
|
|
* Float
|
|
**/
|
|
Add(new JSONMapping(
|
|
typeof(float),
|
|
(JSONMapper arg1, object arg2) => new JSONNumber((float)arg2),
|
|
(JSONMapper arg1, JSONValue arg2) => (float)Decimal.ToDouble(((JSONNumber)arg2).Decimal)
|
|
));
|
|
Add(new JSONMapping(
|
|
typeof(double),
|
|
(JSONMapper arg1, object arg2) => new JSONNumber((double)arg2),
|
|
(JSONMapper arg1, JSONValue arg2) => Decimal.ToDouble(((JSONNumber)arg2).Decimal)
|
|
));
|
|
|
|
/**
|
|
* Strings
|
|
**/
|
|
|
|
Add(new JSONMapping(
|
|
typeof(string),
|
|
(JSONMapper arg1, object arg2) => new JSONString((string)arg2),
|
|
(JSONMapper arg1, JSONValue arg2) => ((JSONString)arg2).Value
|
|
));
|
|
|
|
/**
|
|
* Others
|
|
**/
|
|
|
|
Add(new JSONMapping(
|
|
typeof(bool),
|
|
(JSONMapper arg1, object arg2) => ((bool)arg2) ? (JSONValue)JSONTrue.Instance : (JSONValue)JSONFalse.Instance,
|
|
(JSONMapper arg1, JSONValue arg2) => (arg2.ValueType == JSONValueType.TRUE) || (arg2.ValueType == JSONValueType.FALSE) ? false : throw new NotSupportedException()
|
|
));
|
|
|
|
Add(new JSONDateTimeMapping());
|
|
Add(new JSONDateTimeOffsetMapping());
|
|
Add(new JSONGuidMapping());
|
|
Add(new JSONIPv4Mapping());
|
|
Add(new JSONNetwork4Mapping());
|
|
Add(new JSONTimeSpanMapping());
|
|
|
|
Add(new JSONRPCCallMapping());
|
|
Add(new JSONRPCResultMapping());
|
|
|
|
}
|
|
|
|
public void Add(JSONMapping mapping)
|
|
{
|
|
mappings[mapping.TargetType] = mapping;
|
|
}
|
|
|
|
private JSONMapping FindMapping(Type targetType)
|
|
{
|
|
if (mappings.ContainsKey(targetType))
|
|
return mappings[targetType];
|
|
if (this != DefaultMapper)
|
|
return DefaultMapper.FindMapping(targetType);
|
|
|
|
if (!targetType.IsPrimitive)
|
|
{
|
|
if (targetType.IsArray)
|
|
{
|
|
Add(new JSONArrayMapping(targetType));
|
|
}
|
|
else if (targetType.IsEnum)
|
|
{
|
|
Add(new JSONEnumMapping(targetType));
|
|
}
|
|
else if (targetType.IsSubclassOf(typeof(Exception)))
|
|
{
|
|
Add(new JSONExceptionMapping(targetType));
|
|
}
|
|
else if (targetType.IsGenericType)
|
|
{
|
|
Type genericTypeDefinition = targetType.GetGenericTypeDefinition();
|
|
if (genericTypeDefinition.Equals(typeof(IEnumerable<>)))
|
|
{
|
|
Add((JSONMapping)Activator.CreateInstance(typeof(JSONEnumerableMapping<>).MakeGenericType(targetType.GetGenericArguments()[0])));
|
|
}
|
|
else if (genericTypeDefinition.Equals(typeof(Dictionary<,>)))
|
|
{
|
|
Add((JSONMapping)Activator.CreateInstance(typeof(JSONDictionaryMapping<,>).MakeGenericType(targetType.GetGenericArguments())));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Add(new JSONObjectMapping(targetType));
|
|
}
|
|
return mappings[targetType];
|
|
}
|
|
|
|
throw new NotSupportedException(targetType.ToString());
|
|
}
|
|
|
|
public T FromJson<T>(string jsonString) => FromJson<T>((JSONObject)JSONParser.Parse(jsonString));
|
|
public T FromJson<T>(JSONValue json) => (T)FromJson(json, typeof(T));
|
|
public object FromJson(string jsonString, Type targetType) => FromJson((JSONObject)JSONParser.Parse(jsonString), targetType);
|
|
public object FromJson(JSONValue json, Type targetType)
|
|
{
|
|
if (json.ValueType == JSONValueType.NULL)
|
|
return null;
|
|
|
|
return FindMapping(targetType).FromJson(this, json);
|
|
}
|
|
public JSONValue ToJson(object value)
|
|
{
|
|
if (value == null)
|
|
return JSONNull.Instance;
|
|
|
|
Type sourceType = value.GetType();
|
|
return FindMapping(sourceType).ToJson(this, value);
|
|
}
|
|
|
|
public void Apply(string jsonString, object o) => Apply((JSONObject)JSONParser.Parse(jsonString), o);
|
|
public void Apply(JSONObject json,object o)
|
|
{
|
|
JSONMapping mapping = FindMapping(o.GetType());
|
|
if (!(mapping is JSONObjectMapping))
|
|
throw new NotSupportedException();
|
|
|
|
JSONObjectMapping objectMapping = mapping as JSONObjectMapping;
|
|
objectMapping.Apply(this, json, o);
|
|
}
|
|
|
|
|
|
}
|
|
}
|