1

I have this simple JSON and I was making deserializing this JSON, so I can get the elements. This is the JSON I have :

{
  "QuestionIDs": [
    "QID1",
    "QID3"
  ],
  "QuestionDefinitions": {
    "Question1": {
      "DETag": "Q1",
      "Config": {
        "QDescription": "UseText"
      },
      "COrder": [
        "1",
        "2",
        "3"
      ],
      "Validation": {
        "Settings": {
          "ForceResponse": "OFF",
          "ForceResponseType": "ON",
          "Type": "None"
        }
      }
    }
  },
  "NextButton": null,
  "PreviousButton": false
}

This is the code I've written :

[DataContract]
public class RootObject
{
    [DataMember]
    public Dictionary<string, Dictionary<string, string>> QuestionDefinitions { get; set; }
    [DataMember]
    public List<string> QuestionIDs { get; set; }
}

QuestionIDs is working just fine. But, QuestionDefinitions isn't working. It says that it is an empty sequence. I'm not sure what's wrong.

I want to be able to access QuestionDefinitions.

I tried with Json.Net. Facing the same issue. I was able to get the simple elements that are out. But, couldn't get to access the QuestionDefinitions.

Any help would be appreciated.

EDIT :

I also tried implementing this class like this :

[DataContract]
public class QuestionDetails
{
    [DataMember]
    public string DETag { get; set; }
    [DataMember]
    [DataMember]
    public List<Configuration> Config { get; set; }
    [DataMember]
    public List<string> ChoiceOrder { get; set; }
    [DataMember]
    public List<Validation> Validation { get; set; }
    [DataMember]
    public List<string> COrder { get; set; }
    [DataMember]
    public string NextButton { get; set; }
    [DataMember]
    public string PreviousButton { get; set; }
}


    [DataContract]
    public class RootObject
    {
        [DataMember]
        public Dictionary<string, QuestionDetails> QuestionDefinitions { get; set; }
        [DataMember]
        public List<string> QuestionIDs { get; set; }
    }
Xonshiz
  • 1,307
  • 2
  • 20
  • 48
  • Do you believe `"Config":{"QDescription":"UseText"}` could be an element of a `Dictionary`? It's a bit more complex than that. – Rafalon Aug 09 '18 at 11:07
  • One method is to copy your JSON and Paste Special - paste json as classes into a visual studio file. This will generate a correct object representation of the json, though you will probably want to fix up some of the naming. – Crowcoder Aug 09 '18 at 11:08
  • quite simply your questiondefinitions object is a lot more complex than a simple object->key mapping which is all your dictionary can cope with. You'll need to create a set of concrete types which match the structure, or cheat and use `dynamic` – ADyson Aug 09 '18 at 11:08
  • What is the type/class definition of `NextButton`? – Rui Jarimba Aug 09 '18 at 11:09
  • @RuiJarimba the question has nothing to do with NextButton – ADyson Aug 09 '18 at 11:10
  • @ADyson in order to properly serialize/deserialize the objects it's useful to know what is the type of NextButton. – Rui Jarimba Aug 09 '18 at 11:12
  • Is the json generated by you? If so, would it be possible to change the json format? The current format makes it hard to work dynamically with it. – croxy Aug 09 '18 at 11:13
  • @RuiJarimba OP is only interested in QuestionDefinitions...it's clear from the question text and also their RootObject class doesn't even have a field placed for NextButton or PreviousButton. I assume they don't care about these values for their purpose. – ADyson Aug 09 '18 at 11:24
  • 1
    Do you have any control over the JSON format? TBH I think JSON which has an unpredictable structure like this is not helpful. The structure should be consistent to allow people to deserialise it predictably. Within QuestionDefinitions should really be an array of question objects. The questionID can be a property within each object. Then you can deserialise to an array reliably every time. – ADyson Aug 09 '18 at 11:31
  • About your edit, please note that `NextButton` and `PreviousButton` are **not** part of `QuestionDetails` in your json. They really belong to `RootObject` – Rafalon Aug 10 '18 at 06:42

3 Answers3

6

Your class strucutre against the JSON getting returned is not correct.

When pasted your JSON in json2csharp.com the following the POCO class which generated:

public class Config
{
    public string QDescription { get; set; }
}

public class Settings
{
    public string ForceResponse { get; set; }
    public string ForceResponseType { get; set; }
    public string Type { get; set; }
}

public class Validation
{
    public Settings Settings { get; set; }
}

public class Question1
{
    public string DETag { get; set; }
    public Config Config { get; set; }
    public List<string> COrder { get; set; }
    public Validation Validation { get; set; }
}

public class QuestionDefinitions
{
    public Question1 Question1 { get; set; }
}

public class RootObject
{
    public List<string> QuestionIDs { get; set; }
    public QuestionDefinitions QuestionDefinitions { get; set; }
    public object NextButton { get; set; }
    public bool PreviousButton { get; set; }
}

Now using the above class as representation of your JSON structure you should be able to deserialize it in to C# object.

The following line of code would do it using NewtonSoft library:

string json = "your json result";
RootObject result = JsonConvert.DeserializeObject<RootObject>(json);

You can even do it from within Visual Studio if you have 2013 or above doing like following as described in this post:

enter image description here

Hope it helps.

Ehsan Sajjad
  • 61,834
  • 16
  • 105
  • 160
2

Changing a little the code in @EhsanSajjad's answer, maybe you could use something like:

public class Config
{
    public string QDescription { get; set; }
}

public class Settings
{
    public string ForceResponse { get; set; }
    public string ForceResponseType { get; set; }
    public string Type { get; set; }
}

public class Validation
{
    public Settings Settings { get; set; }
}

public class Question
{
    public string DETag { get; set; }
    public Config Config { get; set; }
    public List<string> COrder { get; set; }
    public Validation Validation { get; set; }
}

public class RootObject
{
    public List<string> QuestionIDs { get; set; }
    public Dictionary<string, Question> QuestionDefinitions { get; set; }
    public object NextButton { get; set; }
    public bool PreviousButton { get; set; }
}
Rafalon
  • 4,450
  • 2
  • 16
  • 30
  • Same issue as earlier. It's not being populated. – Xonshiz Aug 09 '18 at 11:21
  • It's better than the other attempts, but the issue with this dictionary approach is that Question1 is only one property within QuestionDefinitions, not a wrapper around all the data. QuestionDefinitions should be a single object. Within that there would have to be some way to detect any QuestionN object plus all the fixedobjects – ADyson Aug 09 '18 at 11:28
  • You're right, I'd have to try to run an example, but I can't right now, so I'll probably update my answer this week-end – Rafalon Aug 09 '18 at 13:28
  • Well I don't understand why it's not being populated for Xonshiz then. Maybe dll versions? – Rafalon Aug 11 '18 at 07:16
0

Try this model

public class RootObject
{
    public List<string> QuestionIDs { get; set; }
    public QuestionDefinitions QuestionDefinitions { get; set; }
    public object NextButton { get; set; }
    public bool PreviousButton { get; set; }
}
public class QuestionDefinitions
{
    public Question1 Question1 { get; set; }
    public List<string> COrder { get; set; }
    public Validation Validation { get; set; }
}
public class Question1 {
    public string DETag { get; set; }
    public Config Config { get; set; }
}
public class Config {
    public string QDescription { get; set; }
}
public class Validation {
    public Settings Settings { get; set; }
}
public class Settings
{
    public string ForceResponse { get; set; }
    public string ForceResponseType { get; set; }
    public string Type { get; set; }
}
purna
  • 44
  • 3