如何从实体框架中存在数据模型的json中反序列化对象?

Posted

技术标签:

【中文标题】如何从实体框架中存在数据模型的json中反序列化对象?【英文标题】:How to DeserializeObject from json where data model exist in Entity Framework? 【发布时间】:2019-08-12 16:36:47 【问题描述】:

我有一个传入的 json 对象,它代表从数据库结构中提取的数据。

我想将它映射到实体框架模型,该模型具有来自属性或来自数据库上下文中的模型构建器的定义。

在运行实体框架时,此数据正确映射,因此我知道模型是正确的。

所以使用相同的结构,而不是通过 EF 调用数据库,我从一个 API 中提取,该 API 具有与 entity.Property 列名称相同的传入数据结构。

如何将传入的 json 结构映射到模型对象?

属性

[Table("model_example")]
public class ModelExample

   [Column("property_to_map")] // <-- db column name
   public int PropertyToMap  get; set; 

ModelBuilder:

modelBuilder.Entity<ModelExample>(entity =>

    entity.ToTable("model_example");
    entity.Property(e => e.PropertyToMap).HasColumnName("property_to_map");

传入的 JSON 示例:

  "property_to_map":1    

因此,如果从数据库中提取此数据,它将自动映射到“ModelExample.PropertyToMap”和 ModelExample 代码模型。

如何映射它?有没有办法使用实体框架流程?

更新

我知道如何使用 Newtonsoft 从 json 映射到对象。我正在尝试映射到实体而不必使用映射器。实体框架已经有了这些值,我希望只是使用实体框架配合。

【问题讨论】:

也许可以添加一个您希望发生这种情况的方法调用示例,以及您尝试过的示例或您希望在何处进行此转换的示例。如果这是从客户端接收 JSON 数据并希望自动被解释为实体的情况,我强烈建议不要这样做,来自客户端的数据很容易被篡改,不应该被信任为可以附加到上下文并提交到数据库。 【参考方案1】:

我过去曾使用来自 Newtonsoft 的 JsonConvert.DeserializeObject 来执行此操作。希望这会有所帮助。

class Example 
  public int property_to_map get; set;


class ApiCalls

  public void MakeApiCall() 
     var response = ApiCall();
     var MappedObject = JsonConvert.Deserialize<Example>(response);
     //Do whatever you need now with the mapped object.
  

【讨论】:

这也不是我指的,我知道如何从json转换。我希望得到已经使用的 Example.PropertyToMap 值。也许我不想使用映射器。 哦,好吧,相信你还是可以用newtonsoft的。它有一个属性,您也可以分配蛇案例名称,因此它分配给 PropertyToMap 而不是 property_to_map:***.com/questions/15915503/…【参考方案2】:

好吧,我决定改为更改 Json 字符串,而不是将 json 强制转换为模型。

我通过创建自定义 JsonConverter 并在其中重命名 JProperty 来做到这一点。

    构建一个通用的 JsonConverter 基类

    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; 
        
    
    
    

    构建自定义 JSON 转换器。

    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;
        
    
    

    将 JSON 属性名称 property_to_map 转换为实体属性名称 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;
        
    
    

    每个单词都大写

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

    我怎么称呼它

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

【讨论】:

以上是关于如何从实体框架中存在数据模型的json中反序列化对象?的主要内容,如果未能解决你的问题,请参考以下文章

JSON 解析错误:无法从 START_OBJECT 令牌中反序列化 `byte[]` 的实例

[C#]如何使用Newton.Json从流中反序列化json数据

如何解决错误:无效的 JSON 输入:无法从 START_ARRAY 令牌中反序列化 Topic 实例

如何在 C# 中反序列化多个 JSON 对象?

如何去掉Json字符串中反斜杠

如何在 C++ 非托管代码 Json 中反序列化一个字节 [] 的 json 字符串?