0

I am hitting an API that returns some JSON as follows:

{"stats":{"X":{"Name":"X","Found":"Yes"}},"response":"OK","runtimeMs":798}

I would like to generate C# classes for it and I used json2sharp, it generated classes such as root object which i modified as follows:

public class RootObject
            {
                public Stats stats { get; set; }
                public string response { get; set; }
                public int runtimeMs { get; set; }
            }

            public class Stats
            {
                public string name { get; set; }
            }

            public class Variant
            {
                public string name { get; set; }
                public string Found { get; set; }
            }

The issue i am facing is that in the class Stats I have used name since the json will reply with any name such as X or Y or Z.

I am able to deserialise the JSON into the root object but cannot get any data into the stats class.

JsonConvert.DeserializeObject<RootObject>(response.Content);

Any ideas why i might be doing incorrectly?

evanmcdonnal
  • 46,131
  • 16
  • 104
  • 115
user1144596
  • 2,068
  • 8
  • 36
  • 56

2 Answers2

4

Your problem is similar to this How can I parse a JSON string that would cause illegal C# identifiers?

So, your model should be

public class Variant
{
    public string Name { get; set; }
    public string Found { get; set; }
}


public class RootObject
{
    public Dictionary<string, Variant> stats { get; set; }
    public string response { get; set; }
    public int runtimeMs { get; set; }
}

EDIT

@evanmcdonnal if use a dictionary as shown in the EZI's answer or an object with fields named X, Y, and Z you have to perform nullity or keyexists checks all over the place in order to safely use the object.

I don't think this simple linq is hard to write

rootObj.stats.Values.Where(....); 

or

rootObj.stats.Keys.Select(....); 
Community
  • 1
  • 1
EZI
  • 15,209
  • 2
  • 27
  • 33
0

That is happening because json.NET is looking for a property name in your class which matches the field name in the json. Since name does not resemble anything in the json it finds nothing.

There are a couple of options for how to work around this. You can use an annotation to say what the json field you want to put there is, or you can change the name of the property. However, from you post it sounds like you're saying there could be an object called X or an object called Y in the json, neither of those options will make that deserialize correctly in all cases. I'll edit with some ideas for how you may want to handle that.

Based on OP's comment, here's what you're looking for;

        public class RootObject
        {
            public Stats stats { get; set; }
            public string response { get; set; }
            public int runtimeMs { get; set; }
        }

        public class Stats
        {
            public Varient X { get; set; }
            public Varient Y { get; set; }
            public Varient Z { get; set; }
        }

        public class Variant
        {
            public string name { get; set; }
            public string Found { get; set; }
        }

In other places in your code you just have to have two code paths or do a conversion to avoid doing nullity checks everywhere.

if (myInstance.X != null)
   // it was X that was in the json
else if (myInstace.Y != null)
   // it was Y
else
   // not sure what happened, perhaps neither X nor Y were present.

Now the other option is to make this just an intermediary then you define another type that just has one property named name and you give it a constructor that takes a RootObject and assigns whichever value isn't null to it's name property or whatever you want to call it. I would probably do something like this myself because if use a dictionary as shown in the EZI's answer or an object with fields named X, Y, and Z you have to perform nullity or keyexists checks all over the place in order to safely use the object.

evanmcdonnal
  • 46,131
  • 16
  • 104
  • 115
  • I hate *"filler"* answers – EZI Apr 03 '15 at 20:29
  • @EZI ok... I answered his question which didn't ask for a solution but just a simple 'what is wrong'. I don't know how to concising write an answer because the OP doesn't have a clear enough problem statement so I'm preparing a few examples of options. – evanmcdonnal Apr 03 '15 at 20:30
  • yes that is exactly the problem. it can be object x or y or z. thanks evanmcdonnal – user1144596 Apr 03 '15 at 20:31
  • @user1144596 I edited with what I think is the most practical solution. I can elaborate about converting to a cleaner type after deserializing if the idea isn't clear to you. The other commonly used solution would go down a path similar to this; http://stackoverflow.com/questions/17368484/json-net-how-to-override-serialization-for-a-type-that-defines-a-custom-jsonconv where you override the behavior of the deserializer so that it makes the decision about what json property to put into your C# object. – evanmcdonnal Apr 03 '15 at 20:39