使用 Json.Net 反序列化,将子对象反序列化为包含 JSON 的字符串/类似内容

本文关键字:反序列化 字符串 JSON Net Json 使用 对象 包含 | 更新日期: 2023-09-27 18:37:20

我正在尝试使用 Json 创建一个配置文件,该文件将保存各种类型的对象的配置。

请考虑以下文件:

{
    "cameras": [
        {
            "type": "Some.Namespace.CameraClass",
            "assembly": "Some.Assembly",
            "configuration": {
                "ip": "127.0.0.1",
                "port": 8080
            }
        }
    ]
}

在运行时,我将使用两个"类型"和"程序集"属性来构造支持特定接口的对象,然后我想将配置加载到该对象中。

但是,在编译时,我不知道"配置"将映射到的类型。我想将其保留为 json"属性"并将其馈送到相机对象中,然后让该对象将 json 反序列化为正确的类型。

因此,我想将配置文件中包含特定相机类型配置的部分"携带"到对象本身中,并让它处理它,在我这样携带它时将其视为黑匣子。应该保留该部分的结构,因为我希望在为每个相机实现创建配置类型时保持完全保真,甚至在必要时添加子对象。

对于这个特定的相机,我将配置一个IP地址和一个端口,对于其他一些相机,

我需要授权数据,而对于其他一些相机

,我将配置一个完全不同的东西。

我希望保存此配置的属性直接获取 Json,仍然作为字符串。

这可能吗?

下面是一个 LINQPad 示例,其中注释了一些位:

void Main()
{
    const string configurationFile = @"[
    {
        ""type"": ""UserQuery+Camera1"",
        ""configuration"": { ""id"": 10 }
    },
    {
        ""type"": ""UserQuery+Camera2"",
        ""configuration"": { ""name"": ""The second camera"" }
    }
]";
    var cameras = JsonConvert.DeserializeObject<Camera[]>(configurationFile);
    foreach (var camera in cameras)
    {
        var type = Type.GetType(camera.Type);
        var instance = Activator.CreateInstance(type, new object[0]) as ICamera;
        // instance.Configure(camera.Configuration);
    }
}
public class Camera
{
    public string Type { get; set; }
    public JObject Configuration { get; set; }
}
public interface ICamera
{
    void Configure(string json);
}
public class Camera1 : ICamera
{
    private class Configuration
    {
        public int Id { get; set; }
    }
    public void Configure(string json)
    {
        JsonConvert.DeserializeObject<Configuration>(json).Dump();
    }
}
public class Camera2 : ICamera
{
    private class Configuration
    {
        public string Name { get; set; }
    }
    public void Configure(string json)
    {
        JsonConvert.DeserializeObject<Configuration>(json).Dump();
    }
}

两个注释掉的位,即 Camera 类中的属性和对 Configure 方法的调用,是我想要工作的。

是否有我可以标记该属性

的东西,或者我可以为该属性选择的其他类型,这将使它工作?

我知道我可以使属性动态化,这会在其中填充一个JObject,但是每个相机实现的每个Configure方法都必须处理JObject而不是已知的非动态类型。

使用 Json.Net 反序列化,将子对象反序列化为包含 JSON 的字符串/类似内容

如果您

使用类型 JObject 的属性,则看起来解析但保留了 JSON:

using System;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;    
public class Foo
{
    public string Name { get; set; }
    public int Age { get; set; }
    public JObject Configuration { get; set; }
}
public class Test
{
   public static void Main()
   {
       var json = File.ReadAllText("test.json");
       var foo = JsonConvert.DeserializeObject<Foo>(json);
       Console.WriteLine(foo.Configuration);
   }
}

Test.json:

{
  "name": "Jon",
  "age": 10,
  "configuration": {
    "ip": "127.0.0.1",
    "port": 8080
  }
}

输出:

{
  "ip": "127.0.0.1",
  "port": 8080
}

我怀疑你可以直接从JObject反序列化,但如果你真的愿意,你总是可以把它转换回string

如果第二级配置只是一个字符串:

{
    "cameras": [
        {
            "type": "Some.Namespace.CameraClass",
            "assembly": "Some.Assembly",
            "configuration": "{ '"ip'": '"127.0.0.1'", '"port'": 8080 }"
        }
    ]
}

这映射到一个类:

public class Camera
{
    public string Type { get; set; }
    public string Assembly { get; set; }
    public string Configuration { get; set; }
}

然后,您可以执行第二级反序列化,如您的问题中所示。