Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/275.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用Json.Net反序列化,将子对象反序列化为字符串/类似的Json?_C#_Json.net - Fatal编程技术网

C# 使用Json.Net反序列化,将子对象反序列化为字符串/类似的Json?

C# 使用Json.Net反序列化,将子对象反序列化为字符串/类似的Json?,c#,json.net,C#,Json.net,我正在尝试使用Json创建一个配置文件,该文件将保存各种类型对象的配置 考虑以下文件: { "cameras": [ { "type": "Some.Namespace.CameraClass", "assembly": "Some.Assembly", "configuration": { "ip": "127.0.0.1", "por

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

考虑以下文件:

{
    "cameras": [
        {
            "type": "Some.Namespace.CameraClass",
            "assembly": "Some.Assembly",
            "configuration": {
                "ip": "127.0.0.1",
                "port": 8080
            }
        }
    ]
}
在运行时,我将使用两个“type”和“assembly”属性来构造支持特定接口的对象,然后我希望将配置加载到该对象中

然而,在编译时,我不知道“配置”将映射到的类型。我希望将其保留为json“属性”,并将其提供给camera对象,然后让该对象将json反序列化为正确的类型

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

对于这个特殊的摄像头,我将配置一个IP地址和一个端口,对于其他一些摄像头,我需要授权数据,而对于其他一些摄像头,则需要完全不同的配置

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

这可能吗

下面是一个注释掉一些位的示例:

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();
    }
}
void Main()
{
常量字符串配置文件=@“[
{
“”类型“”:“”UserQuery+Camera1“”,
“配置”“:{”“id”“:10}”
},
{
“”类型“”:“”UserQuery+Camera2“”,
“配置”“:{”“名称”“:”“第二个摄像头”“}”
}
]";
var cameras=JsonConvert.DeserializeObject(配置文件);
foreach(摄像机中的var摄像机)
{
var type=type.GetType(camera.type);
var instance=Activator.CreateInstance(类型,新对象[0])作为ICamera;
//instance.Configure(camera.Configuration);
}
}
公共级摄像机
{
公共字符串类型{get;set;}
公共作业对象配置{get;set;}
}
公共接口ICamera
{
void配置(字符串json);
}
公共级摄像机1:ICamera
{
私有类配置
{
公共int Id{get;set;}
}
公共void配置(字符串json)
{
JsonConvert.DeserializeObject(json.Dump();
}
}
公共级摄像机2:伊卡梅拉
{
私有类配置
{
公共字符串名称{get;set;}
}
公共void配置(字符串json)
{
JsonConvert.DeserializeObject(json.Dump();
}
}
两个注释掉的位,即
Camera
类中的属性和对
Configure
方法的调用,是我想要处理的

有什么东西我可以标记该属性,或者我可以为该属性选择其他类型的东西,可以让它工作吗


我知道我可以将属性设置为动态,这会将
JObject
填充到属性中,但是每个摄影机实现的每个
Configure
方法都必须处理
JObject
而不是已知的非动态类型。

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

{
    "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; }
}

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

如果您使用类型为
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);
   }

}
输出:

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

我怀疑您可以直接从
JObject
反序列化,但如果您真的愿意,您可以始终将其转换回
字符串。

当前方法中的静态键入方式是什么?您没有
ip
port
的任何属性,实际上也没有任何表示配置的类。您可能会尝试将属性类型设置为
JObject
,但同样地,您没有intellisense。我不确定您希望如何获得Intellisense…在正在加载的特定类型中,我将获取配置的Json并将其反序列化到一个私有的已知配置对象中。换句话说,加载配置文件的外部代码会认为这是一个黑箱,但是实际的相机实现可以将它反序列化为已知的类型。但是照相机。配置< /代码>在编译时不会是具体的类型,那么您希望智能感知如何工作?如果我键入
camera.Configuration.
您希望看到哪些属性?正如我所说,JObject可能会提供您想要的,但我没有尝试过。我附加了我假设的配置方法。为什么不将整个摄像头配置作为字符串存储在顶级JSON文件中呢。当摄像机反序列化时,这个字符串恰好是有效的JSON…我没有想到将它序列化回字符串。这是应用程序启动,通常会有1-5个摄像头,一个额外的json魔术级别不是问题,这似乎是一个可行的解决方案。请看一看我添加到问题中的LINQPad示例,看看这是否激发了一些新的想法,但这似乎真的很好。在我的示例中,对
Configure
的调用现在是:
instance.Configure(JsonConvert.SerializeObject(camera.Configuration))。这似乎是目前我能做的最好的了。@LasseV.Karlsen:你有没有试过在
JObject
上调用
ToObject(Type)
TObject
?没有,我现在正在研究这种方法,看起来非常有用,似乎我根本不需要来回转换,虽然这可能是内部正在做的。我知道我可以做到这一点,但我想避免所有这些转义字符。然而,@Jon的回答给了我想要的。是的,我必须获取json,反序列化它,将其中的一小部分序列化回json字符串,然后
{
  "ip": "127.0.0.1",
  "port": 8080
}