5

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?

dbc
  • 104,963
  • 20
  • 228
  • 340
  • **Serialization** of `ExpandoObject` works in .NET 5, see https://dotnetfiddle.net/oG4PHv. The expando gets interpreted as an `IDictionary`. To deserialize free-form JSON to dynamic you could use `ObjectAsPrimitiveConverter` from [C# - Deserializing nested json to nested Dictionary](https://stackoverflow.com/q/65972825/3744182) and set `objectFormat = ObjectFormat.Expando`. – dbc Feb 15 '21 at 17:53

1 Answers1

3

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"]}
tymtam
  • 31,798
  • 8
  • 86
  • 126
  • Thanks for remind. We decided to use the Newtonsoft JSON back because our project used so huge queries by dynamic object result with Dapper. This project is use to as a hub service of data which query and assemble from many business systems. As the relations of data objects are often fixed in a very long time and data object change often is only add or delete some fields, use way of dynamic object tech that we need not modify any code and it will still run well. – StarryLibra Oct 22 '19 at 01:53