Destroy Json Objects with Json.Net

I am trying to deserialize an object using Json.net. I was able to do this successfully, but it's more of a hack, so I'm looking for a better / correct way to do this.

{
"page":"admin",
"context":"id",
"records":{
            "rCount":6,
            "1":[
               {
                  "name":"Romeo",
                  "dob":"01\/01\/1970"
               },
               {
                  "name":"Harry",
                  "dob":"10\/10\/2012"
               },
               {
                  "name":"Lee",
                  "dob":"17\/10\/2012"
               }],
            "2":[
               {
                  "name":"Mark",
                  "dob":"01\/01\/1970"
               },
               {
                  "name":"Jack",
                  "dob":"10\/10\/2012"
               },
               {
                  "name":"Json",
                  "dob":"17\/10\/2012"
               }],

}}

      

it is a json string, problem with records object . if it does not have this rCount variable , it can be deserialized as a dictionary, but due to the rCount variable , it cannot be deserialized properly as a dictionary. What should be the proper way to deserialize this object.

Here is my solution:

class Program
{
static void Main(string[] args)
{
    var recordFile = JsonConvert.DeserializeObject<RecordFile>(Properties.Resources.data);
}

public class RecordFile
{
    public string Page { get; set; }
    public string Context { get; set; }
    public Records Records { get; set; }
}

public class Records
{
    public int RCount { get; set; }
    [JsonExtensionData]
    private Dictionary<string, object> _reocordList;

    public List<Record[]> RecordList
    {
        get
        {
            if (_reocordList != null && _reocordList.Count > 0)
            {
                return _reocordList.Values.Select(record => JsonConvert.DeserializeObject<Record[]>(record.ToString())).ToList();
            }
            return new List<Record[]>();
        }
    }

}

public class Record
{
    public string Name { get; set; }
    public string Dob { get; set; }
}
}

      

+3


source to share


3 answers


You can use jObject to parse JSON manually:

public class RecordFile
{
    public string Page { get; set; }
    public string Context { get; set; }
    public Records Records { get; set; }
}

public class Records
{
    public int RCount { get; set; }
    public IDictionary<string, List<Record>> RecordsDictionary { get; set; } 
}


public class Record
{
    public string Name { get; set; }
    public string Dob { get; set; }
}

      

Then:



var jObject = JObject.Parse(\* your json *\);
var recordFile = new RecordFile
{
    Page = jObject.Value<string>("page"),
    Context = jObject.Value<string>("context"),
    Records = new Records
    {
        RCount = jObject["records"].Value<int>("rCount"),
        RecordsDictionary =
            jObject["records"].Children<JProperty>()
                              .Where(prop => prop.Name != "rCount")
                              .ToDictionary(prop => prop.Name),
                                            prop =>
                                            prop.Value.ToObject<List<Record>>())
    }

};

      

Of course, it is easy to handle cases where the property is missing.

+1


source


I assume you want to get rid of the class entirely Records

, end up with something like this:

public class RecordFile
{
    public string Page { get; set; }
    public string Context { get; set; }
    public Dictionary<string, Record[]> Records { get; set; }
}

public class Record
{
    public string Name { get; set; }
    public string Dob { get; set; }
}

      

Since you don't care at all about the property records.rCount

from JSON, you can specify a new error handler to just ignore the property:



var recordFile = JsonConvert.DeserializeObject<RecordFile>(
    jsonString, 
    new JsonSerializerSettings 
    {
        Error = (sender, args) =>
        {
            if (args.ErrorContext.Path == "records.rCount")
            {
                // Ignore the error
                args.ErrorContext.Handled = true;
            }
        }
    });

      

Now, when an error occurs with a given property, the deserializer will simply skip it. Another option would be to write a custom converter, but it feels like overkill, just ignore one property.

Example: https://dotnetfiddle.net/3svPqk

+1


source


The rest of the answers posted so far should work. For the sake of completeness, I'll show you how you can use a custom one JsonConverter

to solve this problem and also simplify your model a bit.

Here is the code for the converter:

class RecordFileConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(RecordFile));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jo = JObject.Load(reader);
        RecordFile rf = new RecordFile();
        rf.Page = (string)jo["page"];
        rf.Context = (string)jo["context"];
        JObject records = (JObject)jo["records"];
        rf.RecordCount = (int)records["rCount"];
        rf.Records = records.Properties()
                            .Where(p => p.Name != "rCount")
                            .Select(p => p.Value.ToObject<Record[]>())
                            .ToList();
        return rf;
    }

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

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

      

To work with the converter, modify the model classes as shown below. (Note that the class RecordFile

has an attribute JsonConverter

to associate a user RecordFileConverter

. Also note that the class Records

has been deleted, and the properties RCount

and RecordList

have been moved to the RecordFile

class and renamed.)

[JsonConverter(typeof(RecordFileConverter))]
public class RecordFile
{
    public string Page { get; set; }
    public string Context { get; set; }
    public int RecordCount { get; set; }
    public List<Record[]> Records { get; set; }
}

public class Record
{
    public string Name { get; set; }
    public string Dob { get; set; }
}

      

Then deserialize as usual:

var recordFile = JsonConvert.DeserializeObject<RecordFile>(json);

      

Demo : https://dotnetfiddle.net/jz3zUT

+1


source







All Articles