I'm parsing this JSON in .net with newtonsoft.json and using json2csharp.com to get the classes I need.
{
"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 gives me:
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
}
And the Param
object contains all the params. So whenever I deserialize it I get 31 List<Param>
objects with all the properties empty except for one.
What i'm looking for is get one Param object with all the 31 properties set.
Unfortunately I can't change JSON format to something like following (which reflects how I want to read it):
"param": {
"camera_clock": "2015-09-03 04:42:20",
"video_standard": "NTSC" ,
"app_status": "idle"
// there are 30+ properties structured that way
}
2 Answers 2
If you want your Param
object to have a fixed set of properties corresponding to the array of properties shown in your JSON, you're going to need to write a custom JsonConverter
that bubbles the properties out of the array and into a single object. Thus:
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();
}
}
Then use it like:
var settings = new JsonSerializerSettings { Converters = new[] { new ArrayToObjectConverter<Param>() } };
var root = JsonConvert.DeserializeObject<RootObject>(jsonString, settings);
Note that I did not do (re-)serialization as an array of objects, as your question doesn't ask for it.
The answer uses the following class definitions:
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; }
}
Prototype fiddle.
3 Comments
Let me see if I understood every thing, when you generate your C# classes you will recive something like that:
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; }
}
After you will use NewtonSoft to deserialize?
you have to do somthing like
myClass deserializedProduct = JsonConvert.DeserializeObject<myClass>(output);
is that you want ?
Hope this help
3 Comments
Explore related questions
See similar questions with these tags.
"param"
property is an array of 32 objects with one property each. So what Json2CSharp is giving you is correct. If you can't control how that JSON is created, then you will need to write a custom deserializer. They are very easy in Newtonsoft.