Ian Goldby
Ian Goldby

Reputation: 6186

Deserialize arbitrary JSON keys and raw values

Using JSON.Net I want to deserialize a JSON object that looks something like this:

"properties": {
    "foo": 1,
    "bar": "Fred",
    "baz": [694481.61, 693638.0, 692624.65, 692354.54]
}

and end up with a dictionary<string,string> that looks like this:

{ "foo", "1" },
{ "bar", "\"Fred\"" },
{ "baz", "[694481.61, 693638.0, 692624.65, 692354.54]" }

The key points to note are:

  1. The keys are not known in advance. (Hence the use of a dictionary rather than deserializing to a class with predefined properties foo, bar and baz.)
  2. The value strings in the dictionary are the raw JSON text from the JSON stream. So strings include their encapsulating quotation marks, and arrays include their encapsulating square brackets.

What I have tried so far

  1. Parse the values as JRaw objects. This would work if I knew the key names in advance: I could declare matching properties in my class as type JRaw - e.g. public JRaw foo { get; set; }. But the key names are not predefined so I can't.
  2. Create a RawValueDictionaryConverter : JsonConverter custom converter that takes the stream and deserializes it directly to a dictionary<string,string>. I thought this would be straightforward, but the raw text of the original stream is not available inside ReadJson(); the stream has already been tokenized and ReadJson() only receives the interpreted token and token type.
  3. Write my own tokenizer and forget about using Json.NET. It may come to this but I don't want to 'reinvent the wheel.'

Upvotes: 1

Views: 2136

Answers (1)

DavidG
DavidG

Reputation: 119066

You can deserialise to Dictionary<string, JRaw> which gets you half way there. For example:

//Example class
public class Root
{
    public Dictionary<string, JRaw> properties { get; set; }
}

var json = "<from the question>";
var result = JsonConvert.DeserializeObject<Root>(json);

foreach (var property in result.Properties)
{
    var value = property.Value.ToString();
}

If you still want the values as strings, you can convert like this:

var stringDictionary = result.Properties.ToDictionary(p => p.Key, p => p.ToString());

Upvotes: 3

Related Questions