-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support "dynamic" and writable DOM #29690
Comments
No, this feature is not supported at this point but something we should consider for vNext. Do you have an example usage to motivate the feature request? Marking as future.
|
@ahsonkhan GraphQL is a good example. The spec recomends JSON but it is not tied to any specific serialization in the response. With ExpandoObject I think that we could enforce the access of the dynamic "data" like a common object |
@ahsonkhan another example is Configuration Service in our project. It exposes collection like REST endpoints, which create collections in MongoDB (it is not just a dummy REST wrapper, and rest collections and mongo collection do not have exact 1-1 mapping, it also asserts certain rules). So in our project we need dynamic/ExpandoObject support. We use it in other microservices as well. |
We also ran into this limitation. Our use case is gradually building a dynamic object before json serialization. Went back to the more mature Json.NET serializer. |
Hey guys whats the walk around for now? |
@MickeyReznikov : See https://stackoverflow.com/questions/15455304/deserialize-a-property-as-an-expandoobject-using-json-net or google “json.net expandoobject” |
@MickeyReznikov, was your question answered? I believe @SidShetye meant going back to using |
I also have a use-case for this - I just want to call a REST API with HttpClient and retrieve a single property from the response. I do not want to create a dedicated class just to parse the response... With JSON.NET I could just use "dynamic" and access the property of choice. |
From https://github.com/dotnet/corefx/issues/41472 by @ghost1372:
|
In our many many applications we are controlling the fields of data from the stored procedures and dynamically render the List and Search List pages with jquery.jtable Without JsonSerializer built-in support for ExpandoObject we cannot use dotnet core built-in Json Serialization |
We do share the same use case as already mentioned by @estiller and @SidShetye |
Is it possible to have a milestone closer to now than Future? 🤔 ExpandoObject's been in the BCL for a looooong time |
Is there any alternative for ExpandoObject? |
@fatihyildizhan No there is no alternate. but we have written our own ExpandoObject converter, you can take the hint from this article ASP.NET Core 3.0: Custom JsonConverter for the new System.Text.Json We need only the serialization, so we just create the serialization |
I was surprised this isn't supported yet. |
Moving this to 5.0. |
Moving to 5.0? That means we have to wait for a year at least? Back to JSON.Net it is. |
5.0? wow, that definitely sucks. |
For temporal ugly workaround I can use JsonDocument with custom converter for it, but it is IDisposable.
|
We are no longer able to use the following POST action in the presence of System.Text.Json: [HttpPost]
public async Task<IActionResult> SubmitAsync(dynamic model) Instead, we had to use the following method but there was no straight forward to use 'model' in the downstream backend code: [HttpPost]
public async Task<IActionResult> SubmitAsync(JsonElement model) 'model' is a complex object and it may contain a collection of objects and/or other nested complex objects. To be able to conclude a Can I assume that addressing this ticket/issue implies a fix for our issue that we've been experiencing? It seems to be a bit urgent issue to address, so can it be addressed sooner than later? |
.NET Core 3.0 JsonSerializer.Deserialize to dynamic objectJsonSerializer support for ExpandoObject(Interim measures) Add the Json Converteradd using:
/// <summary>
/// Temp Dynamic Converter
/// by:[email protected]
/// </summary>
public class DynamicJsonConverter : JsonConverter<dynamic>
{
public override dynamic Read(ref Utf8JsonReader reader,
Type typeToConvert,
JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.True)
{
return true;
}
if (reader.TokenType == JsonTokenType.False)
{
return false;
}
if (reader.TokenType == JsonTokenType.Number)
{
if (reader.TryGetInt64(out long l))
{
return l;
}
return reader.GetDouble();
}
if (reader.TokenType == JsonTokenType.String)
{
if (reader.TryGetDateTime(out DateTime datetime))
{
return datetime;
}
return reader.GetString();
}
if (reader.TokenType == JsonTokenType.StartObject)
{
using JsonDocument documentV = JsonDocument.ParseValue(ref reader);
return ReadObject(documentV.RootElement);
}
// Use JsonElement as fallback.
// Newtonsoft uses JArray or JObject.
JsonDocument document = JsonDocument.ParseValue(ref reader);
return document.RootElement.Clone();
}
private object ReadObject(JsonElement jsonElement)
{
IDictionary<string, object> expandoObject = new ExpandoObject();
foreach (var obj in jsonElement.EnumerateObject())
{
var k = obj.Name;
var value = ReadValue(obj.Value);
expandoObject[k] = value;
}
return expandoObject;
}
private object? ReadValue(JsonElement jsonElement)
{
object? result = null;
switch (jsonElement.ValueKind)
{
case JsonValueKind.Object:
result = ReadObject(jsonElement);
break;
case JsonValueKind.Array:
result = ReadList(jsonElement);
break;
case JsonValueKind.String:
//TODO: Missing Datetime&Bytes Convert
result = jsonElement.GetString();
break;
case JsonValueKind.Number:
//TODO: more num type
result = 0;
if (jsonElement.TryGetInt64(out long l))
{
result = l;
}
break;
case JsonValueKind.True:
result = true;
break;
case JsonValueKind.False:
result = false;
break;
case JsonValueKind.Undefined:
case JsonValueKind.Null:
result = null;
break;
default:
throw new ArgumentOutOfRangeException();
}
return result;
}
private object? ReadList(JsonElement jsonElement)
{
IList<object?> list = new List<object?>();
foreach (var item in jsonElement.EnumerateArray())
{
list.Add(ReadValue(item));
}
return list.Count == 0 ? null : list;
}
public override void Write(Utf8JsonWriter writer,
object value,
JsonSerializerOptions options)
{
// writer.WriteStringValue(value.ToString());
}
} How to Use?var serializerOptions = new JsonSerializerOptions
{
Converters = { new DynamicJsonConverter() }
};
return JsonSerializer.Deserialize<dynamic>("{OK:"200"}", serializerOptions); |
@tchivs, your solution worked for me; but since the Converters property is read-only, I had to do something like this: var serializerOptions = new JsonSerializerOptions();
serializerOptions.Converters.Add(new DynamicJsonConverter());
return JsonSerializer.Deserialize<dynamic>("{OK:"200"}", serializerOptions); |
Try using the JsonElement type:
|
@tchivs, I made some modifications to your code -- reworking it so that it uses dynamically generated "projection" types (having a subset of properties from a base type), rather than ExpandoObject. I posted the code (in a sample console project) here: EDennis.DynamicDeserialization. I will be testing this approach with more complicated objects and under various scenarios (e.g., deserialization of dynamic objects used to patch existing, fully typed EF Core entities; deserialization of json objects and arrays for test cases). Let me know if you find this useful or if you see anything problematic. |
Thanks for the community workaround. It's surprising Microsoft are unable to put out this feature in a sensible timeframe. Working with GraphQL responses without dynamic object of some sort leads to lots of verbose and ugly code. Or even just checking for existence of deeply nested properties. |
I read through the thread of comments and most are focused on deserialization, I'm facing an issue where also serialization of dynamic objects apparently silently "fails". In an attempt to reproduce my scenario I came up with the following minimal repro:
When run Is this the right issue? or should I raise/follow a different one? |
This is the right issue. No need to open one for the two halves of the same feature. This issue is about adding support for expando object (which means for both sides, serialize and deserialize). |
New functions ([v] indicates test coverage): [v] net.fetch_endpoints [v] net.set_endpoints + Module error code enums. + TonUtil utility class containing two methods ATM: `LoadAbi` and `LoadTvc`. + `JsonExtensions` containing `ToJson` extension method to construct `JToken`'s from anonymous types (the recommended way). TODO: 1. Get rid of `Newtonsoft.Json` dependency (maybe). Currently it's only used because it provides a useful API for selecting data from the arbitrary-typed objects (JToken) returned by the SDK. While `System.Text.Json` still lacks support of dynamic type objects dotnet/runtime#29690. 2. More examples.
New functions ([v] indicates test coverage): [v] net.fetch_endpoints [v] net.set_endpoints + Module error code enums. + `TonUtil` utility class containing two methods ATM: `LoadAbi` and `LoadTvc`. + `JsonExtensions` containing `ToJson` extension method to construct `JToken`'s from anonymous types (the recommended way). TODO: 1. Get rid of `Newtonsoft.Json` dependency (maybe). Currently it's only used because it provides a useful API for selecting data from the arbitrary-typed objects (JToken) returned by the SDK. While `System.Text.Json` still lacks support of dynamic type objects dotnet/runtime#29690. 2. More examples.
I saw many people in this issue talk about the |
The proposal for 6.0 is to support for
Can you elaborate on "correcting" to make sure we have the scenario. I assume you mean changing the DOM to modify a value of a property\element or by adding\removing properties\elements. |
yes, for example change the but today the we don't need a |
Seems weird C# doesn't have a standard library to manipulate JSON data, only serialize, deserialize from static types, or read only an arbitrary json document. Really need to be able to read, query and to manipulate JsonDocument, add elements, remove elements, etc and then turn it back to a string. The simple pain of getting any arbitrary piece of json and adding an extra element to it is astonishing. Think you guys need to implement a library that allows full manipulation of JSON data, not just a means to and end for deserializing/serializing static types. |
in .NET there are 2 standards: 3rd party Nuget package Json.NET and .NET Core’s built-in classes here is an example of manipulating a JSON file without deserializing with the built in Json classes:
(from: C# 8.0 in a Nutshell) |
@steveharter - I'm unable to get your PR Code sample for supporting dynamic objects #42097 to load consistently - most of the time it won't load. I also noticed that the example is missing a |
Am I the only one who want a JSON POCO Object in C# (eg. and @rs38 you solution is about write, and a mutable JSON DOM is about change and read (or write) // do some change to the original JSON
var jobj = xxxx.Parse(Request.Body) as JObject;
if(ShouldInjectClaim == true)
{
jobj.Add("Claims", JArray.Parse(new []{ "claim1". "claim2" }));
}
// handle the "data"
DoSomething(jobj); // mostly read again
|
@John0King I don't think you're the only person, that's part of what this issue is about. Have you seen dotnet/designs#163? @udlose not sure why GitHub is having trouble loading the PR. You can always check out the commit: 095539f or even just browse to these tests that are now part of the product.
I think that's just because the sample was minimal. I see @steveharter mentions this in the design doc: |
Closing; the Preview 5 will also add some new capabilities for |
@steveharter , @ericstj I pulled Steve's code sample for supporting
I can easily change these from |
It looks to me like a compiler error around a identifier resolution, where something in another assembly is resolving to that Value member when it didn't before. It could be something unrelated to the update. If you have an issue to report (even against sample code) it's better to open a new issue and provide us with full details and a repro, that way we can better reproduce and diagnose what you are seeing. Also, if you're willing to grab a nightly build you can try the official feature which is in as of last week: https://dev.azure.com/dnceng/public/_packaging?_a=package&feed=dotnet6&package=System.Text.Json&protocolType=NuGet&version=6.0.0-preview.5.21229.9 Thanks! |
You can also try this
|
For those still interested in dynamic how valuable is that now that we have a writable DOM with Please add your comments to this issue: #53195 |
Does
JsonSerializer.Parse(String, Type, JsonSerializerOptions)
support for dynamicExpandoObject
return type?Something like this:
dynamic p = JsonSerializer.Parse(json, typeof(ExpandoObject));
The text was updated successfully, but these errors were encountered: