3

I'm getting a string of json as a stream and trying to deserialize it to a Dictionary<string, string> the problem with that is that it chokes on numbers, even when the serialize options are set. How does one do this with System.Text?

Program.cs with .NET 6:

using System;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;


Console.WriteLine("Converting Json...");
var result = await DeserializeJson();
Console.WriteLine($"result: {result}");


async Task<Dictionary<string, string>> DeserializeJson()
{
    var jsonText = "{\"number\": 709, \"message\": \"My message here\",\"bool\": true}";
    var stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonText));

    var options = new JsonSerializerOptions 
    { 
         PropertyNameCaseInsensitive = true,
         NumberHandling = JsonNumberHandling.WriteAsString 
    };
    var fullResponse = await JsonSerializer.DeserializeAsync<Dictionary<string, string>>(stream, options);

    return fullResponse;
}

The main error that results:

---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.

This would make sense if it wasn't for the fact that I set the handle numbers property of the serialization options. Is that known to be failing or is something wrong here?

1

1 Answer 1

5

Your json does not contain only strings. As a quick (but not performant one) fix you can try to deserealize to Dictionary<string, object> and then convert it to Dictionary<string, string>:

async Task<Dictionary<string, string>> DeserializeJson()
{
    var jsonText = "{\"number\": 709, \"message\": \"My message here\",\"bool\": true}";
    var stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonText));

    var options = new JsonSerializerOptions 
    { 
        PropertyNameCaseInsensitive = true,
        NumberHandling = JsonNumberHandling.WriteAsString ,
        
    };
    var fullResponse = await JsonSerializer.DeserializeAsync<Dictionary<string, Object>>(stream, options);

    return fullResponse?.ToDictionary(pair => pair.Key, pair => pair.ToString());
}

Or parse the document manually:

async Task<Dictionary<string, string>> DeserializeJson()
{
    var jsonText = "{\"number\": 709, \"message\": \"My message here\",\"bool\": true}";
    var stream = new MemoryStream(Encoding.UTF8.GetBytes(jsonText));
  
    using var jsonDocument = JsonDocument.Parse(stream);
    var dictionary = jsonDocument.RootElement
        .EnumerateObject()
        .ToDictionary(property => property.Name, property => property.Value.ToString());
    return dictionary;
}
Sign up to request clarification or add additional context in comments.

3 Comments

Is there a way to just "make everything strings" even if it's just a ref number instead of the nested object?
@CoderLee can you please provide an example of json?
I only care about the one I have in the question, but you're welcome to use a more detailed example.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.