读取JSON,其中属性是嵌套数组而不是对象的属性

时间:2016-01-28 18:09:01

标签: c# .net json serialization json.net

我正在使用newtonsoft.json在.net中解析这个JSON,并使用json2csharp.com来获取我需要的类。

{
"rval": 0,
"msg_id": 3,
"param": [{ "camera_clock": "2015-09-03 04:42:20" },
          { "video_standard": "NTSC" },
          { "app_status": "idle" }
          // there are 30+ properties structured that way
         ]
}

json2csharp给了我:

public int rval { get; set; }
public int msg_id { get; set; }
public List<Param> param { get; set; }

class Param 
{
     public string camera_clock {get;set;}
     public string video_standard {get;set;}
     public string app_status {get;set;}
     // 30+ more
}

Param对象包含所有参数。因此,每当我反序列化它时,我会得到31个List<Param>个对象,除了一个属性外,所有属性都是空的。 我正在寻找的是获得一个Param对象,其中包含31个属性集。

不幸的是我无法将 JSON格式更改为以下内容(这反映了我想要阅读的内容):

"param": { 
   "camera_clock": "2015-09-03 04:42:20",
   "video_standard": "NTSC" ,
   "app_status": "idle" 
   // there are 30+ properties structured that way
 }

2 个答案:

答案 0 :(得分:2)

如果您希望Param对象拥有与JSON中显示的属性数组相对应的固定属性集,那么您需要编写一个custom JsonConverter来清除属性数组和单个对象。因此:

public class ArrayToObjectConverter<T> : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(T).IsAssignableFrom(objectType);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;

        if (existingValue == null)
        {
            var contract = serializer.ContractResolver.ResolveContract(objectType);
            existingValue = contract.DefaultCreator();
        }

        switch (reader.TokenType)
        {
            case JsonToken.StartArray:
                {
                    var jArray = JArray.Load(reader);

                    var jObj = new JObject();
                    foreach (var prop in jArray.OfType<JObject>().SelectMany(o => o.Properties()))
                        jObj.Add(prop);

                    using (var sr = jObj.CreateReader())
                    {
                        serializer.Populate(sr, existingValue);
                    }
                }
                break;

            case JsonToken.StartObject:
                serializer.Populate(reader, existingValue);
                break;

            default:
                var msg = "Unexpected token type " + reader.TokenType.ToString();
                Debug.WriteLine(msg);
                throw new JsonSerializationException(msg);
        }

        return existingValue;
    }

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

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

然后使用它:

        var settings = new JsonSerializerSettings { Converters = new[] { new ArrayToObjectConverter<Param>() } };
        var root = JsonConvert.DeserializeObject<RootObject>(jsonString, settings);

请注意,我没有(重新)序列化作为对象数组,因为您的问题没有要求它。

答案使用以下类定义:

public class Param
{
    public string camera_clock { get; set; }
    public string video_standard { get; set; }
    public string app_status { get; set; }
    public string stream_out_type { get; set; }
    public string save_low_resolution_clip { get; set; }
    public string video_resolution { get; set; }
    public string video_stamp { get; set; }
    public string video_quality { get; set; }
    public string timelapse_video { get; set; }
    public string photo_size { get; set; }
    public string photo_stamp { get; set; }
    public string photo_quality { get; set; }
    public string timelapse_photo { get; set; }
    public string selfie_photo { get; set; }
    public string burst_photo { get; set; }
    public string autoshoot_photo { get; set; }
    public string loop_record { get; set; }
    public string motion_detec_video { get; set; }
    public string status_led_switch { get; set; }
    public string wifi_led_switch { get; set; }
    public string osd_switch { get; set; }
    public string cardvr_switch { get; set; }
    public string delay_pwroff { get; set; }
    public string rotate_image { get; set; }
    public string mic_vol { get; set; }
    public string language { get; set; }
    public string date_disp_fmt { get; set; }
    public string auto_bkl_off { get; set; }
    public string auto_pwr_off { get; set; }
    public string light_freq { get; set; }
    public string meter_mode { get; set; }
    public string buzzer { get; set; }
}

public class RootObject
{
    public int rval { get; set; }
    public int msg_id { get; set; }
    public Param param { get; set; }
}

原型fiddle

答案 1 :(得分:-1)

让我看看我是否理解了所有的东西,当你生成C#类时,你会看到类似的东西:

public class Param
{
    public string camera_clock { get; set; }
    public string video_standard { get; set; }
    public string app_status { get; set; }
    public string stream_out_type { get; set; }
    public string save_low_resolution_clip { get; set; }
    public string video_resolution { get; set; }
    public string video_stamp { get; set; }
    public string video_quality { get; set; }
    public string timelapse_video { get; set; }
    public string photo_size { get; set; }
    public string photo_stamp { get; set; }
    public string photo_quality { get; set; }
    public string timelapse_photo { get; set; }
    public string selfie_photo { get; set; }
    public string burst_photo { get; set; }
    public string autoshoot_photo { get; set; }
    public string loop_record { get; set; }
    public string motion_detec_video { get; set; }
    public string status_led_switch { get; set; }
    public string wifi_led_switch { get; set; }
    public string osd_switch { get; set; }
    public string cardvr_switch { get; set; }
    public string delay_pwroff { get; set; }
    public string rotate_image { get; set; }
    public string mic_vol { get; set; }
    public string language { get; set; }
    public string date_disp_fmt { get; set; }
    public string auto_bkl_off { get; set; }
    public string auto_pwr_off { get; set; }
    public string light_freq { get; set; }
    public string meter_mode { get; set; }
    public string buzzer { get; set; }
}

public class myClass
{
    public int rval { get; set; }
    public int msg_id { get; set; }
    public List<Param> param { get; set; }
}

您将使用NewtonSoft进行反序列化吗?

你必须做像

这样的事情
myClass deserializedProduct = JsonConvert.DeserializeObject<myClass>(output);

是你想要的吗?

希望这个帮助