Asked  6 Months ago    Answers:  5   Viewed   32 times

I'm trying to parse some JSON using the JSon.Net library. The documentation seems a little sparse and I'm confused as to how to accomplish what I need. Here is the format for the JSON I need to parse through.

{
    "displayFieldName" : "OBJECT_NAME", 
    "fieldAliases" : {
        "OBJECT_NAME" : "OBJECT_NAME", 
        "OBJECT_TYPE" : "OBJECT_TYPE"
    }, 
    "positionType" : "point", 
    "reference" : {
        "id" : 1111
    }, 
    "objects" : [ {
        "attributes" : {
            "OBJECT_NAME" : "test name", 
            "OBJECT_TYPE" : "test type"
        }, 
        "position" : {
            "x" : 5, 
            "y" : 7
        }
    } ]
}

The only data I really need from this is the stuff in the objects array. Is it possible for me to parse through that with something like the JSonTextReader and just pull out the things I want, like OBJECT_TYPE and the x and y position? I can't seem to get JSonTextReader to work the way I want it to and I find little to no examples of usage for it.

It seems like serializing first then using LINQ with my object would be ideal and every example I find discusses serializing the JSON first, but I'm not sure how I would build an object for this structure. Particularly the objects array which would need to be something like a list of Pairs of attribute and position objects. I have no idea how I would code my object so JSon.Net would know how to serialize that.

I thought I could write my own simple parser to just pull out everything I need into an attributes object that I created, but I'm having little luck.

Hopefully this all makes sense, any ideas?

 Answers

32

I don't know about JSON.NET, but it works fine with JavaScriptSerializer from System.Web.Extensions.dll (.NET 3.5 SP1):

using System.Collections.Generic;
using System.Web.Script.Serialization;
public class NameTypePair
{
    public string OBJECT_NAME { get; set; }
    public string OBJECT_TYPE { get; set; }
}
public enum PositionType { none, point }
public class Ref
{
    public int id { get; set; }
}
public class SubObject
{
    public NameTypePair attributes { get; set; }
    public Position position { get; set; }
}
public class Position
{
    public int x { get; set; }
    public int y { get; set; }
}
public class Foo
{
    public Foo() { objects = new List<SubObject>(); }
    public string displayFieldName { get; set; }
    public NameTypePair fieldAliases { get; set; }
    public PositionType positionType { get; set; }
    public Ref reference { get; set; }
    public List<SubObject> objects { get; set; }
}
static class Program
{

    const string json = @"{
  ""displayFieldName"" : ""OBJECT_NAME"", 
  ""fieldAliases"" : {
    ""OBJECT_NAME"" : ""OBJECT_NAME"", 
    ""OBJECT_TYPE"" : ""OBJECT_TYPE""
  }, 
  ""positionType"" : ""point"", 
  ""reference"" : {
    ""id"" : 1111
  }, 
  ""objects"" : [
    {
      ""attributes"" : {
        ""OBJECT_NAME"" : ""test name"", 
        ""OBJECT_TYPE"" : ""test type""
      }, 
      ""position"" : 
      {
        ""x"" : 5, 
        ""y"" : 7
      }
    }
  ]
}";


    static void Main()
    {
        JavaScriptSerializer ser = new JavaScriptSerializer();
        Foo foo = ser.Deserialize<Foo>(json);
    }


}

Edit:

Json.NET works using the same JSON and classes.

Foo foo = JsonConvert.DeserializeObject<Foo>(json);

Link: Serializing and Deserializing JSON with Json.NET

Tuesday, June 1, 2021
 
Szenis
answered 6 Months ago
77

Json isn't a huge language to start with, so libraries for it are likely to be small(er than Xml libraries, at least).

There are a whole ton of C libraries linked at Json.org. Maybe one of them will work well for you.

Wednesday, June 9, 2021
 
Deyson
answered 6 Months ago
99

You can create a custom contract resolver that sets the property names back to the ones you've defined in the C# class before serilization. Below is some example code;

class OriginalNameContractResolver : DefaultContractResolver
{
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        // Let the base class create all the JsonProperties 
        IList<JsonProperty> list = base.CreateProperties(type, memberSerialization);

        // assign the C# property name
        foreach (JsonProperty prop in list)
        {
            prop.PropertyName = prop.UnderlyingName;
        }

        return list;
    }
}

Use it like this;

    JsonSerializerSettings settings = new JsonSerializerSettings();
    settings.Formatting = Formatting.Indented;
    if (useLongNames)
    {
        settings.ContractResolver = new OriginalNameContractResolver();
    }

    string response = JsonConvert.SerializeObject(obj, settings);
Thursday, August 12, 2021
 
Puneet
answered 4 Months ago
71

Okay, so here's basically what I ended up doing (in case anybody else needs something similar). My collection looks something like this:

    [JsonConverter(typeof(MyDataJsonConverter))]
    public class MyData<S,T> : IList<Tuple<S,T>>
    {
        private List<Tuple<S, T>> _data;
        // all the implementation of IList...
    }

And my custom converter (now no longer nested inside MyData) looks like this:

internal class MyDataJsonConverter : JsonConverter
{

    public override bool CanConvert(Type objectType)
    {
        return objectType.IsGenericType && objectType.GetGenericTypeDefinition() == typeof(MyData<,>);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // Note: this is strictly for serializing, deserializing is a whole other
        // ball of wax that I don't currently need!
        throw new NotImplementedException();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var obj = value as IEnumerable<dynamic>;
        object[][] dataArray = (from dp in obj
                                select new object[] { dp.Item1, dp.Item2 }).ToArray();
        var ser = new JsonSerializer();
        ser.Serialize(writer, dataArray);
    }

    public override bool CanRead
    {
        get
        {
            return false;
        }
    }
}
Tuesday, August 24, 2021
 
daniel__
answered 3 Months ago
61

Just to close the loop:

For the project in question, we ended up going with cJSON. We chose this one from the list of C libraries linked from json.org. Per the homepage, cJSON is:

An ultra-lightweight, portable, single-file, simple-as-can-be ANSI-C compliant JSON parser, under MIT license.

This happened to be a good fit for the particular project at hand, and the library worked out fine.

Friday, August 27, 2021
 
Tom Lilletveit
answered 3 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share