【问题标题】:How to force c# NewtonSoft deserializer to use already created object for deserialization如何强制 c# NewtonSoft 反序列化器使用已创建的对象进行反序列化
【发布时间】:2018-04-24 13:18:05
【问题描述】:

在做的时候

JsonConvert.DeserializeObject(value, type);

根据给定的type 创建一个新对象以进行反序列化。我的要求是我想使用已经创建的对象进行反序列化

CustomObject obj = new CustomObject(); //passing constructor args
JsonConvert.DeserializeObject(value, obj);    

但是这个重载是不可用的。

那么,有什么解决方法可以让我使用已经创建的对象,而不是通过 Deserializer 创建新类型。

我为什么要这样做? (详细)

我正在编写一个从 JSON 到 c# 类的通用映射器。 JSON的结构看起来像

  {
    "ActionType" : "LogEvent", //this is actually class name in a specific namespace
    "Settings"   : {
           "FailureRetries" : 4,
           "LogChannel"     : 1234 // log channel id, implementation detail
     }
  }

我在配置映射器中做的如下

public void IAction GetActionFromConfig(){

    dynamic config = configManager.Load<dynamic>(); //loads JSON file.
    string className = config.ActionType; //from config we will get file name.
    Type type = Type.GetType(nameSpaceForConfig + "." + className);

    string  settingValue = JsonConvert.SerializeObject(config.Settings);
    object actionObject = JsonConvert.DeserializeObject(settingValue, type);

    return (IAction)actionObject; // return the IAction from config.
}

我的问题是IAction 实现类可能在构造函数中有一些依赖项(例如ILogger),默认情况下,反序列化不会初始化构造函数参数。我知道我可以覆盖 JsonConverter 以进行构造函数初始化,但由于我正在编写通用映射器,因此我无法使用自定义 JsonConverter 提供特定参数。

我打算首先创建一个字典,将Type(c#Type 类)映射到特定实现以进行依赖解析。

其次,我将获取给定操作类型的构造函数(在配置中使用ActionType 参数给出的类型)

Type type = Type.GetType(nameSpaceForConfig + "." + className);
var ctors = typeof(type).GetConstructors();
var ctor = ctors[0];
List<Type> constructorArguments = new List<Type();
foreach (var param in ctor.GetParameters())
{
     constructorArguments.Add(param.ParameterType);
}

然后我将查询在步骤 1 中创建的字典。以获取构造函数的参数。

最后,我将使用Activator.CreateInstance()(传递上一步获得的构造函数依赖项)。

然后使用这个对象进行反序列化,通过配置文件初始化公共属性。

所以,这就是为什么我需要在 object 而不是 type 上进行反序列化。

注意:前提条件是每个动作都应该有一个包含所有依赖项的构造函数。

旁白:configManager.Load&lt;T&gt; 实现

public T Load<T>() where T : class, new() => Load(typeof(T)) as T;
public object Load(Type type)
{
  if (!File.Exists(_configurationFilePath))
    return Activator.CreateInstance(type);

  var jsonFile = File.ReadAllText(_configurationFilePath);

  return JsonConvert.DeserializeObject(jsonFile, type, JsonSerializerSettings);
}

【问题讨论】:

标签: c# json serialization reflection json.net


【解决方案1】:

您应该使用JsonConvert.PopulateObject 方法来填充现有对象。见here

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    • 2019-02-02
    相关资源
    最近更新 更多