Skip to content
This repository has been archived by the owner on Apr 28, 2020. It is now read-only.

Implement ORM #4

Open
AlenPelin opened this issue May 16, 2017 · 2 comments
Open

Implement ORM #4

AlenPelin opened this issue May 16, 2017 · 2 comments

Comments

@AlenPelin
Copy link

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);
  }  
}
@AlenPelin
Copy link
Author

As a temporary workaround it may be easier to convert Json5 to Json and use Json.NET.

@AlenPelin
Copy link
Author

AlenPelin commented May 16, 2017

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<>);
    }

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant