Monday, July 25, 2022

[FIXED] How to deserialize a json string or stream to Dictionary<string,string> with System.Text.Json

Issue

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?


Solution

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;
}


Answered By - Guru Stron
Answer Checked By - Marie Seifert (PHPFixing Admin)

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.