如何在不事先知道对象类型的情况下使用Json.net反序列化对象列表



我有一个包含多行json的文本文件,每行代表几种类型中的一种。例如,文件中的第一行可能表示序列化的Foo,而第二行表示序列化的Bar,依此类推

问题是如何反序列化这些行?(反序列化要求您指定要使用的类型,但我事先不知道每行代表哪种类型)

起初,我尝试在序列化程序上使用TypeNameHandling = TypeNameHandling.Objects,它将字段名$type嵌入到序列化的json中。这看起来很有希望。我想我可以把每一行都读成一个动态对象,就像这样:

var o = JsonConvert.DeserializeObject<dynamic>(line_from_file);

然后提取出$type字段,然后使用它来反序列化一个具体的类,如下所示:

var concrete_object = JsonConvert.DeserializeObject<(type indicated in $type)>(line_from_file);

但是在上面从动态反序列化返回的o对象中,似乎无法访问$type字段名。

我想我可以用文本解析每一行,寻找$type,但这似乎也很混乱。

在序列化时使用TypeNameHandling = TypeNameHandling.Objects的全部意义在于,不必进行任何特殊处理即可反序列化回特定类型。只要在反序列化时也指定TypeNameHandling = TypeNameHandling.Objects,反序列化程序就会读取嵌入的$type属性,并为您实例化/填充正确的对象。(请注意,DeserializeObject具有用于此目的的非通用重载,不需要指定Type参数;这可能是您感到困惑的原因。)

下面是一个往返演示程序来说明这一点。它将创建几个测试对象,将它们序列化到一个临时JSON文件中,如您的问题中所述,然后重新读取该文件,将每一行反序列化回一个对象,并将其类型和内容转储到控制台。

class Program
{
    static void Main(string[] args)
    {
        Foo foo = new Foo { Id = 1, Name = "foo" };
        Bar bar = new Bar { Length = 2.3, Width = 1.6 };
        JsonSerializerSettings settings = new JsonSerializerSettings
        {
            TypeNameHandling = TypeNameHandling.Objects,
            Formatting = Formatting.None      // ensure no line breaks in the JSON
        };
        string fileName = @"C:tempQ37034748.json";
        // Write out sample file, one object per line
        using (StreamWriter sw = new StreamWriter(fileName, false, Encoding.UTF8))
        {
            sw.WriteLine(JsonConvert.SerializeObject(foo, settings));
            sw.WriteLine(JsonConvert.SerializeObject(bar, settings));
        }
        // Now read the file, deserializing each line to an object and dumping it out
        using (StreamReader sr = new StreamReader(fileName, Encoding.UTF8))
        {
            while (!sr.EndOfStream)
            {
                object obj = JsonConvert.DeserializeObject(sr.ReadLine(), settings);
                Dump(obj);
            }
        }
    }
    private static void Dump(object obj)
    {
        if (obj != null) 
        {
            Type type = obj.GetType();
            Console.WriteLine(type.FullName);
            foreach (PropertyInfo prop in type.GetProperties())
            {
                Console.WriteLine(prop.Name + ": " + prop.GetValue(obj));
            }
        }
        else
        {
            Console.WriteLine("null");
        }
        Console.WriteLine();
    }
}
class Foo
{
    public int Id { get; set; }
    public string Name { get; set; }
}
class Bar
{
    public double Length { get; set; }
    public double Width { get; set; }
}

JSON文件将类似于此(您的命名空间/程序集名称可能不同):

{"$type":"JsonTest.Foo, JsonTest","Id":1,"Name":"foo"}
{"$type":"JsonTest.Bar, JsonTest","Length":2.3,"Width":1.6}

控制台输出将如下所示:

JsonTest.Foo
Id: 1
Name: foo
JsonTest.Bar
Length: 2.3
Width: 1.6

相关内容

  • 没有找到相关文章

最新更新