我搜索了类似的问题,找不到与我想要的完全匹配的任何东西。
C#的新手请跟我说。
我有一些我正在反序列化的json文件。我希望文件反序列化为正确类型的对象,而不必事先定义类型。这是我的代码:
public class loadJson
{
//path of the file location
public void readJson(string path)
{
//array of files at the path location. right now just reading one file
FileInfo[] files = new DirectoryInfo(path).GetFiles("seleniumExample.json").ToArray();
foreach (FileInfo fi in files)
{
dynamic b1 = null;
using (StreamReader file = new StreamReader(fi.FullName))
{
string fileText = file.ReadToEnd();
//Console.WriteLine(fileText);
try
{
b1 = Newtonsoft.Json.JsonConvert.DeserializeObject(fileText);
}
catch(Exception e)
{
Console.WriteLine("ERROR!!!! " + e.ToString());
}
file.Close();
}
}
}
}
我有一堆对象类型,我将通过json文件提供给我的程序。
我不想明确地将b1称为Bid,客户或任何其他特定的预定义类。如果我明确地将b1称为出价,它会加载所有信息,并填写正确的实例变量。
但是当我使用“动态”或一般的“对象”时,它无法解决它并只是初始化为“对象”。
有没有办法执行泛型反序列化并让它根据json文件中定义的字段创建正确类的对象?
提前感谢您的帮助,如果我的问题非常不清楚,我会道歉。如果是这样,请让我知道如何帮助消除任何歧义。再次感谢。
答案 0 :(得分:14)
Json.NET能够使用设置TypeNameHandling = TypeNameHandling.Auto
在序列化期间记录.Net对象类型的多态类型。启用该设置后,.Net类型的多态对象将显示为名为"$type"
的合成属性for instance:
"$type": "Newtonsoft.Json.Samples.Stockholder, Newtonsoft.Json.Tests"
但是,如果您调用常规方法JsonConvert.SerializeObject(Object)
或JsonSerializer.Serialize(TextWriter, Object)
,则 root 对象永远不会发出"$type"
属性。相反,您必须使用一种接受“预期”根类型的序列化方法,例如SerializeObject(Object, Type, JsonSerializerSettings)
或JsonSerializer.Serialize(TextWriter, Object, Type)
。将typeof(object)
作为预期类型传递可确保显示type属性:
var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto };
var json = JsonConvert.SerializeObject(rootObject, typeof(object), settings);
如果使用此设置创建JSON文件,JSON本身将记住序列化对象的类型。只要您将TypeNameHandling
设置为TypeNameHandling.None
之外的其他内容,Json.NET将在反序列化期间使用此类型。 e.g:
var settings = new Newtonsoft.Json.JsonSerializerSettings { TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Auto };
b1 = Newtonsoft.Json.JsonConvert.DeserializeObject(fileText, settings);
工作样本.Net小提琴here。
警告:这种在JSON中存储.Net类型的方式是非标准的。其他序列化程序(如DataContractJsonSerializer
)不会以此格式处理类型信息。
请注意Newtonsoft docs:
中的这一注意事项当您的应用程序从外部源反序列化JSON时,应谨慎使用TypeNameHandling。使用非None以外的值进行反序列化时,应使用自定义SerializationBinder验证传入类型。
有关为何需要这样做的讨论,请参阅TypeNameHandling caution in Newtonsoft Json,How to configure Json.NET to create a vulnerable web API和AlvaroMuñoz& Oleksandr Mirosh的黑帽纸https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf。
答案 1 :(得分:0)
将您的JSON反序列化为最基本的形式:
Dictionary<string, object> theData= new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(jsonString);
string baseItemName = (string)theData["baseItem"];
Dictionary<string, object> someNode= (Dictionary<string, object>)theData["something"];
string anything = (string)someNode["anything"];
string nothing = (string)someNode["nothing"];
对Deserialize()
的调用会创建一个Dictionary<string, object>
树,您可以随意浏览。