3

I have JSON which looks like:

{
  "name": "foo",
  "settings": {
    "setting1": true,
    "setting2": 1
  }
}  

I know how to use json2csharp.com to create the C# classes to deserialize this. They looks like:

public class Settings
{
    public bool settings1 { get; set; }
    public int settings2 { get; set; }
}

public class RootObject
{
    public string name { get; set; }
    public Settings settings { get; set; }
}

but what I want is to simply deserialize it into

public class RootObject
{
    public string name { get; set; }
    public string settings { get; set; }
}

i.e., all of the "setting" JSON just needs to be saved as a string--the structure of that JSON is not consistent. How can that be done? Thanks!

John
  • 223
  • 3
  • 13
  • 2
    Instead of going to a string (unless this is really what you want), you could probably get this to go into some sort of dictionary. I answered something similar here: https://stackoverflow.com/questions/23505096/deserialize-json-with-dynamic-objects/23520523#23520523 – Pete Garafano Aug 08 '18 at 21:07
  • @PeteGarafano. I do need it as a string, you I think that you have the right idea. I just need to do it like: `code` var rawObj = JsonConvert.DeserializeObject(json); var uniq = rawObj.name; var settings = rawObj.settings; `code` thanks for the idea – John Aug 08 '18 at 21:37
  • @John see my answer, I don't think using dynamic here is the "cleanest" solution. – MistyK Aug 08 '18 at 21:40
  • @John I did it with `dynamic` in that answer, but nothing is stopping you from making it into a `Dictionary` or something similar. If it helped at all, I'll call it a win. Good luck! – Pete Garafano Aug 08 '18 at 23:54

4 Answers4

4

You could use a JToken to capture your unknown settings during deserialization, then use a second property to allow you to access that JSON as a string if you need to.

Set up your class like this:

public class RootObject
{
    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonIgnore]
    public string Settings
    {
        get { return SettingsToken != null ? SettingsToken.ToString(Formatting.None) : null; }
        set { SettingsToken = value != null ? JToken.Parse(value) : JValue.CreateNull(); }
    }

    [JsonProperty("settings")]
    private JToken SettingsToken { get; set; }
}

Then deserialize as usual:

var root = JsonConvert.DeserializeObject<RootObject>(json);

The Settings property will contain the settings part of the JSON as a string. If you reserialize the object back to JSON then the settings will retain whatever structure it had before.

You can also change the Settings property to some other JSON string, as long as it is well-formed. (If it isn't, then an exception will be thrown immediately.)

Here is a round-trip demo: https://dotnetfiddle.net/thiaWk

Brian Rogers
  • 125,747
  • 31
  • 299
  • 300
  • 1
    Brilliant! This works perfectly and I was able to easily adapt this for another challenge I had. Thanks!!! – John Aug 09 '18 at 14:31
2

Try using Newtonsoft.Json plus LINQ:

string jsonText = @"{
            'name': 'foo',
            'settings': {
                'settings1': true,
                'settings2': 1
                }
            }";

JObject jObj = JObject.Parse(jsonText);
var setting = jObj.Descendants()
                .OfType<JProperty>()
                .Where(p => p.Name == "settings")
                .First()
                .Value.ToObject<Settings>();
CDurand
  • 54
  • 4
1

Try this:

public class RootObject
        {
            public string name { get; set; }
            public Dictionary<string,object> settings { get; set; }
        }

Fiddle: https://dotnetfiddle.net/QN3nWL

MistyK
  • 6,055
  • 2
  • 42
  • 76
  • I can't redefine the RootObject like this and the real object is more complex and it will not always go into a Dictionary, but +1 for the dotnetfiddle. I like those! – John Aug 08 '18 at 21:45
  • @John why can't it go to dictionary? Dictionary represents any object structure in .NET – MistyK Aug 09 '18 at 13:12
  • Yes, it does work to parse the json, but I really need to leave that as a string property. – John Aug 10 '18 at 14:07
0

I have just this solution:

public class RootObject
        {
            public string name { get; set; }
            public Settings settings { get; set; }
            public string strSettings { get; set; } <-------- 
        }

and

  var data= Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(json);
    data.strSettings = Newtonsoft.Json.JsonConvert.SerializeObject(data.settings);
Hossein
  • 3,083
  • 3
  • 16
  • 33
  • This wont work. He said the structure of the Settings is not consistent so you can't use a Settings class like that. – Nick Aug 08 '18 at 21:19