反序列化动态JSON文件C#NewtonSoft.JSON [英] Deserialize Dynamic JSON file C# NewtonSoft.JSON

查看:494
本文介绍了反序列化动态JSON文件C#NewtonSoft.JSON的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在反序列化可能包含2个单独的类,我不知道哪种类型的数据将是阵列中的动态JSON文件的工作。



问题是我反序列化根对象键入基地,测验对象序列化,以分测验,但测验数组可能是类型的基地或类型的子测试。



问:
我怎么会去编程判断,如果对象包含分测验,我反序列化基地,如果没有,就应该反序列化到分测验?



我真的很感激这一个,因为我在很短的时间线中的帮助。



(编辑:添加注释,以显示每一个对象应该反序列化到什么类型)
下面是一个例子(JSON数据):

  {
//反序列化键入基地
主人:123456,
:LAST_TIMEBREAK:2014年9月15日07:04:49.205000 ,
名:MYNAME,
结果:不及格,
系列:12345,
START_TIME:2014-09- 15 06:53:36.976000,
//反序列化到类型列表<&子测试GT;
测验:[
{
数据:{
MOREDATA:{
版本:123,
实:123
}
},
说明:数据说明,
主人:123456,
:LAST_TIMEBREAK:2014 -09-15 20:32:31.095000,
名:testname.py,
结果:PASS,
START_TIME:2014-09- 15 20:32:25.873000,
版本:2.014.09.15
},
{
//嵌套子测试阵列中,应反序列化键入基地再次
主人:123456,
:LAST_TIMEBREAK:2014年9月15日07:04:49.205000,
名:测试套件的名称,
结果:不及格,
START_TIME:2014年9月15日06:53:36.976000,
//应该反序列化为类型列表<&子测试GT;
测验:[
{
说明:数据说明,
主人:123456,
:LAST_TIMEBREAK:2014 -09-15 06:53:40.440000,
名:testname.py,
结果:不及格,
START_TIME:2014-09- 15 06:53:36.976000,
版本:2.014.09.15
},
{
说明:考试说明,
举办:123456,
:LAST_TIMEBREAK:2014年9月15日06:54:34.905000,
名:testname.py,
结果: PASS,
START_TIME:2014年9月15日06:54:34.827000,
版本:2.014.09.15
},
$ { b $ b主人:123456,
:LAST_TIMEBREAK:2014年9月15日06:55:01.156000,
名:testname.py,
结果:FAIL,
START_TIME:2014年9月15日06:55:01.156000,
版本:2.014.09.15
},

],
版本:1.45
}
],
版本:1.23
}

示例(代码):

 公共类基地{
公共字符串主机{搞定;组; }
公众的DateTime:LAST_TIMEBREAK {搞定;组; }
公共字符串名称{;组; }
公共字符串结果{搞定;组; }
公共字符串序列{搞定;组; }
公众的DateTime START_TIME {搞定;组; }
公开名单<&子测试GT;测验{搞定;组; }
公共字符串版本{搞定;组; }
}

公共类子测试{
[JsonProperty(数据)]
公共JObject数据{搞定;组; } //检查

[JsonProperty(说明)]
公共字符串描述{搞定;组; } //检查

[JsonProperty(主机)]
公共字符串主机{搞定;组; }

[JsonProperty(信息)
公开名单< StatusDetails>信息{搞定;组; }

[JsonProperty(:LAST_TIMEBREAK)]
公众的DateTime LastRunTime {搞定;组; }

[JsonProperty(名称)]
公共字符串测试名{获得;组; }

[JsonProperty(结果)]
公共字符串SubtestRunResult {搞定;组; }

[JsonProperty(START_TIME)]
公共DateTime的开始时间{搞定;组; }

[JsonProperty(跟踪)]
公开名单<对象>跟踪{搞定;组; }

[JsonProperty(版本)]
公共字符串版本{搞定;组; }
}


解决方案

我要返工你的类以形成一个分层结构。我可能在这里缺少一个属性,但你得到的图片。 。最重要的一点是转换器

 公共抽象类TestBase 
{
公共字符串主机{搞定;组; }

[JsonProperty(:LAST_TIMEBREAK)]
公众的DateTime LastTime {搞定;组; }

公共字符串名称{;组; }
公共字符串结果{搞定;组; }

[JsonProperty(START_TIME)]
公共DateTime的开始时间{搞定;组; }
公共字符串版本{搞定;组; }
}

公共类的TestSuite:TestBase
{
公共字符串序列{搞定;组; }
公开名单< TestBase>测验{搞定;组; }
}

公共类子测试:TestBase
{
公共JObject数据{搞定;组; }

公共字符串描述{搞定;组; }
}



然后,你需要一个自定义的转换器来选择基础上,正确的类型

 公共类TestBaseConverter:JsonConverter $ b中的测验属性的存在$ b {
公众覆盖对象ReadJson(
JsonReader读者,
类型的objectType,
对象existingValue,
JsonSerializer串行)
{
JObject OBJ = serializer.Deserialize< JObject>(读卡器);

TestBase结果= NULL;

如果(OBJ [测验]!= NULL)
{
结果=新的TestSuite();
}
,否则
{
结果=新的子测试();
}

serializer.Populate(obj.CreateReader(),结果);

返回结果;
}

公众覆盖布尔CanConvert(类型的objectType)
{
返回的typeof(TestBase).IsAssignableFrom(的objectType);
}

公众覆盖布尔CanWrite
{
获得{返回false; }
}

公共覆盖无效WriteJson(
JsonWriter作家,对象的值,JsonSerializer串行)
{
抛出新NotSupportedException异常();
}
}

您会然后使用它是这样的:

 的TestSuite套件= JsonConvert.DeserializeObject<&TestSuite的GT;(
JSON,新TestBaseConverter());


Working on deserializing a dynamic JSON file which could contain 2 separate classes and I won't know which type of data will be in the array.

The problem is, I deserialize the root object to type "Base", "subtests" objects are deserialized to "Subtest", but the "subtests" array could be of type "Base" or of type "Subtest".

QUESTION: How would I go about programatically determining that if the object contains "subtest", I deserialize to Base, and if it doesn't, it should deserialize to "Subtest"?

I really appreciate the help on this one since I'm on a short timeline.

(EDIT: Added comments to show what type each object should deserialize to) Here's an example (JSON DATA):

{
// Deserializes to type "Base"
  "host": "123456",
  "last_time": "2014-09-15 07:04:49.205000",
  "name": "myName",
  "result": "FAIL",
  "serial": "12345",
  "start_time": "2014-09-15 06:53:36.976000",
// Deserializes to type "List<Subtest>"
  "subtests": [
    {
      "data": {
        "moredata": {
          "ver": "123",
          "real": 123
        }
      },
      "description": "Description of Data",
      "host": "123456",
      "last_time": "2014-09-15 20:32:31.095000",
      "name": "testname.py",
      "result": "PASS",
      "start_time": "2014-09-15 20:32:25.873000",
      "version": "2.014.09.15"
    },
    {
// Nested within Subtest Array, Should deserialize to type "Base" again
      "host": "123456",
      "last_time": "2014-09-15 07:04:49.205000",
      "name": "name of test suite",
      "result": "FAIL",
      "start_time": "2014-09-15 06:53:36.976000",
//Should deserialize to type "List<Subtest>"
      "subtests": [
        {
          "description": "Description of Data",
          "host": "123456",
          "last_time": "2014-09-15 06:53:40.440000",
          "name": "testname.py",
          "result": "FAIL",
          "start_time": "2014-09-15 06:53:36.976000",
          "version": "2.014.09.15"
        },
        {
          "description": "Test Description",
          "host": "123456",
          "last_time": "2014-09-15 06:54:34.905000",
          "name": "testname.py",
          "result": "PASS",
          "start_time": "2014-09-15 06:54:34.827000",
          "version": "2.014.09.15"
        },
        {
          "host": "123456",
          "last_time": "2014-09-15 06:55:01.156000",
          "name": "testname.py",
          "result": "FAIL",
          "start_time": "2014-09-15 06:55:01.156000",
          "version": "2.014.09.15"
        },

      ],
      "version": "1.45"
    }
  ],
  "version": "1.23"
}

Example (CODE):

public class Base{
    public string host { get; set; }
    public DateTime last_time { get; set; }
    public string name { get; set; }
    public string result { get; set; }
    public string serial { get; set; }
    public DateTime start_time { get; set; }
    public List<Subtest> subtests { get; set; }
    public string version { get; set; }
}

public class Subtest {
    [JsonProperty("data")]
    public JObject Data { get; set; } // CHECK

    [JsonProperty("description")]
    public string Description { get; set; } // CHECK

    [JsonProperty("host")]
    public string Host { get; set; }

    [JsonProperty("info")]
    public List<StatusDetails> Info { get; set; }

    [JsonProperty("last_time")]
    public DateTime LastRunTime { get; set; }

    [JsonProperty("name")]
    public string TestName { get; set; }

    [JsonProperty("result")]
    public string SubtestRunResult { get; set; }

    [JsonProperty("start_time")]
    public DateTime StartTime { get; set; }

    [JsonProperty("trace")]
    public List<object> Trace { get; set; }

    [JsonProperty("version")]
    public string Version { get; set; }
}

解决方案

I would rework your classes to form a hierarchy. I'm probably missing a properties here, but you get the picture. The important bit is the converter.

public abstract class TestBase
{
    public string Host { get; set; }

    [JsonProperty("last_time")]
    public DateTime LastTime { get; set; }

    public string Name { get; set; }
    public string Result { get; set; }

    [JsonProperty("start_time")]
    public DateTime StartTime { get; set; }
    public string Version { get; set; }
}

public class TestSuite : TestBase
{
    public string Serial { get; set; }
    public List<TestBase> Subtests { get; set; }
}

public class Subtest : TestBase
{
    public JObject Data { get; set; }

    public string Description { get; set; }
}

Then, you need a custom converter to choose the correct type based on the existence of the subtests property:

public class TestBaseConverter : JsonConverter
{
    public override object ReadJson(
        JsonReader reader,
        Type objectType,
        object existingValue,
        JsonSerializer serializer)
    {
        JObject obj = serializer.Deserialize<JObject>(reader);

        TestBase result = null;

        if (obj["subtests"] != null)
        {
            result = new TestSuite();
        }
        else 
        {
            result = new Subtest();
        }

        serializer.Populate(obj.CreateReader(), result);

        return result;
    }

    public override bool CanConvert(Type objectType)
    {
        return typeof(TestBase).IsAssignableFrom(objectType);
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(
        JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotSupportedException();
    }
}

You would then use it like this:

TestSuite suite = JsonConvert.DeserializeObject<TestSuite>(
    json, new TestBaseConverter());

这篇关于反序列化动态JSON文件C#NewtonSoft.JSON的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆