C# 使用Json.Net反序列化,将子对象反序列化为字符串/类似的Json?
我正在尝试使用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
{
"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
}