json5-dotnet
json5-dotnet copied to clipboard
Implement ORM
It is essential to implement an ORM that will map Json5Object to custom types the same as it is done by Json.NET. For example:
public class Program
{
public string Name { get; set; }
public Program Nested;
public static void Main()
{
var obj = Json5.Parse<Program>("{ name: 'hello world', nested: { name: 'hello parent' } }");
Console.WriteLine(obj.Name);
Console.WriteLine(obj.Nested.Name);
}
}
As a temporary workaround it may be easier to convert Json5 to Json and use Json.NET.
ORM code sample:
[NotNull]
public static T Parse<T>(string json5) where T : class
{
return (T)GetObject((Json5Object)Json5.Parse(json5), typeof(T));
}
[NotNull]
private static object GetObject(IEnumerable<KeyValuePair<string, Json5Value>> dict, Type type)
{
var obj = Activator.CreateInstance(type);
if (obj == null)
{
throw new InvalidOperationException();
}
foreach (var kv in dict)
{
var prop = type.GetProperty(kv.Key, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public);
if (prop == null)
{
continue;
}
object value = kv.Value;
if (value is IEnumerable<KeyValuePair<string, Json5Value>>)
{
value = GetObject((IEnumerable<KeyValuePair<string, Json5Value>>)value, prop.PropertyType);
}
SetValue(prop, obj, value);
}
return obj;
}
private static void SetValue(PropertyInfo field, object targetObj, object value)
{
object valueToSet;
if (value == null || value == DBNull.Value)
{
valueToSet = null;
}
else
{
var propertyType = field.PropertyType;
if (propertyType.IsEnum)
{
valueToSet = Enum.ToObject(propertyType, value);
}
else if (propertyType.IsValueType && IsNullableType(propertyType))
{
var underlyingType = Nullable.GetUnderlyingType(propertyType);
valueToSet = underlyingType.IsEnum ? Enum.ToObject(underlyingType, value) : value;
}
else
{
var converter = value.GetType().GetMethods().FirstOrDefault(x => x.Name == "op_Implicit" && x.ReturnType == propertyType);
if (converter != null)
{
valueToSet = converter.Invoke(null, new[] {value});
}
else
{
valueToSet = Convert.ChangeType(value, propertyType);
}
}
}
field.SetValue(targetObj, valueToSet);
}
private static bool IsNullableType(Type type)
{
return type != null && type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
}