5
votes

I want to convert a dynamic object to json string. It worked perfect when I used Newtonsoft.Json at past. when I upgraded .net core to 3.0 and used System.Text.Json instead, it was bad.

See the code:

using System;
using System.Collections.Generic;
using System.Dynamic;
namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            dynamic product = new ExpandoObject();
            product.ProductName = "Elbow Grease";
            product.Enabled = true;
            product.Price = 4.90m;
            product.StockCount = 9000;
            product.StockValue = 44100;
            product.Tags = new string[] { "Real", "OnSale" };

            // Will output: { "ProductName":"Elbow Grease","Enabled":true,"Price":4.90,
            // "StockCount":9000,"StockValue":44100,"Tags":["Real","OnSale"]}
            var json1 = Newtonsoft.Json.JsonConvert.SerializeObject(product);
            Console.WriteLine(json1);

            // Both will throw exception: System.InvalidCastException:“Unable to
            // cast object of type '<GetExpandoEnumerator>d__51' to type
            // 'System.Collections.IDictionaryEnumerator'.”
            var json2 = System.Text.Json.JsonSerializer.Serialize(product);
            Console.WriteLine(json2);
            var json3 = System.Text.Json.JsonSerializer.Serialize<IDictionary<string, object>>(product as IDictionary<string, object>);
            Console.WriteLine(json3);

            Console.ReadKey();
        }
    }
}

If I want to persist using System.Text.Json to convert the dynamic object because I hear that it is faster then other json converts, how could I do?

1
Serialization of ExpandoObject works in .NET 5, see dotnetfiddle.net/oG4PHv. The expando gets interpreted as an IDictionary<string, object>. To deserialize free-form JSON to dynamic you could use ObjectAsPrimitiveConverter from C# - Deserializing nested json to nested Dictionary<string, object> and set objectFormat = ObjectFormat.Expando.dbc

1 Answers

3
votes

This is logged as JsonSerializer support for ExpandoObject #38007 stil Open as of 2019 Oct 21.

You can use an anonymous type instead.

var product = new {
            ProductName = "Elbow Grease",
            Enabled = true,
            Price = 4.90m,
            StockCount = 9000,
            StockValue = 44100,
            Tags = new string[] { "Real", "OnSale" }
        };


var json1 = Newtonsoft.Json.JsonConvert.SerializeObject(product);
Console.WriteLine(json1);

var json2 = System.Text.Json.JsonSerializer.Serialize(product);
Console.WriteLine(json2);
{"ProductName":"Elbow Grease","Enabled":true,"Price":4.90,"StockCount":9000,"StockValue":44100,"Tags":["Real","OnSale"]}
{"ProductName":"Elbow Grease","Enabled":true,"Price":4.90,"StockCount":9000,"StockValue":44100,"Tags":["Real","OnSale"]}