Search code examples
c#jsonentity-frameworkattributesef-model-builder

How to DeserializeObject from json where data model exist in Entity Framework?


I have an incoming json object that represents the data pulled from a database structure.

I would like to map it to the Entity Framework model which has the definitions either from attributes or from model builder in the DB context.

When running Entity Framework, this data maps correctly so I know the models are correct.

So using the same structure, instead of calling the database through EF, I am pulling from an API that has the same incoming data structure as the entity.Property column names.

How do I map the incoming json structure to the model object?

Attributes

[Table("model_example")]
public class ModelExample
{
   [Column("property_to_map")] // <-- db column name
   public int PropertyToMap { get; set; }
}

Or ModelBuilder:

modelBuilder.Entity<ModelExample>(entity =>
{
    entity.ToTable("model_example");
    entity.Property(e => e.PropertyToMap).HasColumnName("property_to_map");
}

Incoming JSON example:

 { "property_to_map":1 }   

So if this data was pulled from the db it would automatically be mapped to `ModelExample.PropertyToMap' and the ModelExample code model.

How do I map it? Is there a way to use the Entity Framework process?

Update

I know how to map from json to object using Newtonsoft. I'm trying to map to the entity without having to use a mapper. Entity Framework already has these values, I was hoping to just use entity framework tie in.


Solution

  • Ok, instead of forcing the json to the model, I decided to alter The Json string instead.

    I do this by Creating a custom JsonConverter and inside there rename the JProperty.

    1. Build A Generic JsonConverter Base Class

      public abstract class JsonCreationConverter<T> : JsonConverter
      {            
          protected abstract T CreateArray<TJsonType>(Type objectType, TJsonType jObject);
      
          public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
          {
              throw new NotImplementedException("Unnecessary because CanWrite is " +
                                            "false. The type will skip the converter.");
          }
      
          public override object ReadJson(JsonReader reader, Type objectType,
              object existingValue, JsonSerializer serializer)
          {
              if (reader.TokenType == JsonToken.Null)
                  return null;
      
              JArray jArray;
              var target = default(T);
              try
              {
                  jArray = JArray.Load(reader);
                  target = CreateArray<JArray>(objectType, jArray);
              }
              catch (Exception ex)
              {                    
                  return null;
              }
              return target;
          }
      
          public override bool CanConvert(Type objectType)
          {
              return typeof(T).IsAssignableFrom(objectType);
          }
      
          public override bool CanWrite
          {
              get { return false; }
          }
      
      }
      
    2. Build a Custom JSON Converter.

      public class JsonEntityConverter<TObject> : JsonCreationConverter<TObject>       
      {
          protected override TObject CreateArray<TJsonType>(Type objectType, TJsonType tArray)
          {
              var deserializedObj = default(TObject);
      
              var jArray = (JArray)Convert.ChangeType(tArray, typeof(JArray));
      
              var newjArray = new JArray();
      
              foreach (var item in jArray.Children())
              {
                  var itemProperties = item.Children<JProperty>();
      
                  var jObj = new JObject();
                  foreach (var itemProperty in itemProperties)
                  {                    
                      var name = itemProperty.Name.ToModelName();  // <-- Code Below #3                                     
      
                      var newJproperty = new JProperty(name, itemProperty.Value);
                  jObj.Add(newJproperty);
                  }
      
                   newjArray.Add(jObj);
      
              }
      
              var sObject = Newtonsoft.Json.JsonConvert.SerializeObject(newjArray);
      
              deserializedObj = Newtonsoft.Json.JsonConvert.DeserializeObject<TObject>(sObject);
      
              return deserializedObj;
          }
      }
      
    3. Convert the JSON Property Name property_to_map To Entity Property Names PropertyToEmpty

      public static partial class StringsExtensions
      {        
          // Changes example_id to exampleId for mapping
          public static string ToModelName(this string text)
          {
              // First we make a space
              text = text.Replace("_", " ");
      
              // Capitalize every word
              text = text.ToUpperEveryWord(); // <-- Code Below #4                    
      
              // remove the extra space
              text = text.Replace(" ", "");
      
              return text;
          }
      }
      
    4. Capitalize Every Word

      public static string ToUpperEveryWord(this string s)
      {
          // Check for empty string.  
          if (string.IsNullOrEmpty(s))
          {
              return string.Empty;
          }
      
          var words = s.Split(' ');
      
          var t = "";
          foreach (var word in words)
          {
              t += char.ToUpper(word[0]) + word.Substring(1) + ' ';
          }
      
          return t.Trim();
      }
      
    5. How I call it

      var data = Newtonsoft.Json.JsonConvert.DeserializeObject<TType>(item.ToString(), new JsonEntityConverter<TType>());