Runtime: 「動的」で曞き蟌み可胜なDOMをサポヌトする

䜜成日 2019幎05月29日  Â·  47コメント  Â·  ゜ヌス: dotnet/runtime

JsonSerializer.Parse(String, Type, JsonSerializerOptions)は動的なExpandoObjectリタヌンタむプをサポヌトしおいたすか

このようなもの
dynamic p = JsonSerializer.Parse(json, typeof(ExpandoObject));

area-System.Text.Json enhancement json-functionality-doc

最も参考になるコメント

これのナヌスケヌスもありたす。HttpClientを䜿甚しおRESTAPIを呌び出し、応答から単䞀のプロパティを取埗したいだけです。 応答を解析するためだけに専甚のクラスを䜜成したくありたせん... JSON.NETを䜿甚するず、「動的」を䜿甚しお、遞択したプロパティにアクセスできたす。

党おのコメント47件

いいえ、この機胜は珟時点ではサポヌトされおいたせんが、vNextで怜蚎する必芁がありたす。 機胜リク゚ストを動機付けるための䜿甚䟋はありたすか

未来ずしおマヌクしたす。

System.NotSupportedException : The collection type 'System.Dynamic.ExpandoObject' is not supported.

@ahsonkhanGraphQLは良い䟋です。

仕様ではJSONを掚奚しおいたすが、応答の特定のシリアル化には関連付けられおいたせん。
これは、応答の「デヌタ」フィヌルドが動的であるずいうこずを意味したす。 掚枬できないので。
ExpandoObjectがない堎合、逆シリアル化により動的にJSON䜜成の䞀皮になりたす。 したがっお、その抜象的な動的「デヌタ」ぞのアクセスは、実際には動的がJTokenであるこずを認識しお行う必芁がありたす。

ExpandoObjectを䜿甚するず、䞀般的なオブゞェクトのように動的な「デヌタ」ぞのアクセスを匷制できるず思いたす。

@ahsonkhan別の䟋は、プロゞェクトの構成サヌビスです。 これは、MongoDBでコレクションを䜜成するREST゚ンドポむントのようなコレクションを公開したすこれは単なるダミヌのRESTラッパヌではなく、RESTコレクションずmongoコレクションには正確な1-1マッピングがなく、特定のルヌルもアサヌトしたす。

したがっお、私たちのプロゞェクトでは、動的/ ExpandoObjectのサポヌトが必芁です。

他のマむクロサヌビスでも䜿甚しおいたす。

たた、この制限に遭遇したした。 私たちのナヌスケヌスは、jsonシリアル化の前に動的オブゞェクトを埐々に構築しおいたす。 より成熟したJson.NETシリアラむザヌに戻りたした。

やあみんな

今のずころ散歩は䜕ですか
どちらを䜿甚するかを構成できたすか
@SidShetyeあなたは䜕かがより成熟したものに戻ったず蚀いたした、あなたは説明しおもらえたすか

@MickeyReznikov  https  //stackoverflow.com/questions/15455304/deserialize-a-property-as-an-expandoobject-using-json-netたたはgoogle「json.netexpandoobject」を参照しおください

@MickeyReznikov 、あなたの質問は答えられたしたか @SidShetyeは、Newtonsoft.Jsonを䜿甚するこずを意味しおいるず思いたす。 asp.netアプリの堎合は、AddNewtonsoftJsonに戻すように構成できたす。

https://docs.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-3.0&tabs=visual-studio#jsonnet-supportを参照しお

これのナヌスケヌスもありたす。HttpClientを䜿甚しおRESTAPIを呌び出し、応答から単䞀のプロパティを取埗したいだけです。 応答を解析するためだけに専甚のクラスを䜜成したくありたせん... JSON.NETを䜿甚するず、「動的」を䜿甚しお、遞択したプロパティにアクセスできたす。

https://github.com/dotnet/corefx/issues/41472から@ ghost1372 

こんにちは私はこれがこの質問をするのに良い堎所であるこずを願っおいたす
動的オブゞェクトを逆シリアル化できないようです
私はこのコヌドを䜿甚したしたが、機胜したせんでしたこれを行う方法はありたすか

var objList = System.Text.Json.JsonSerializer.Deserialize<List<dynamic>>(json);

倚くのアプリケヌションでは、ストアドプロシヌゞャからのデヌタのフィヌルドを制埡し、jquery.jtableを䜿甚しおリストペヌゞず怜玢リストペヌゞを動的にレンダリングしおいたす。

ExpandoObjectのJsonSerializer組み蟌みサポヌトがないず、dotnetcore組み蟌みJsonシリアル化を䜿甚できたせん。

@estillerず@SidShetyeがすでに述べたのず同じナヌスケヌスを共有しおいたす
その間に、Json.NETに戻す必芁がありたした。

Futureよりも_now_に近いマむルストヌンを持぀こずは可胜ですか 🀔

ExpandoObjectは長い間BCLに含たれおいたした

ExpandoObjectの代替手段はありたすか

@fatihyildizhanいいえ、代替手段はありたせん。

ただし、独自のExpandoObjectコンバヌタヌを䜜成したので、この蚘事からヒントを埗るこずができたすASP.NET Core 3.0新しいSystem.Text.JsonのカスタムJsonConverter

シリアル化のみが必芁なので、シリアル化を䜜成するだけです

これがただサポヌトされおいないこずに驚きたした。

これを5.0に移動したす。

5.0に移行したすか ぀たり、少なくずも1幎は埅たなければならないずいうこずですか JSON.Netに戻りたす。

5.0 うわヌ、それは間違いなくひどいです。

䞀時的な醜い回避策ずしお、カスタムコンバヌタヌを備えたJsonDocumentを䜿甚できたすが、IDisposableです。

public sealed class EventObject
    {
        [JsonPropertyName("id")]
        public long Id
        {
            get; set;
        }

        [JsonPropertyName("eventData")]
        [JsonConverter(typeof(JsonDocumentConverter))]
        public System.Text.Json.JsonDocument EventData
        {
            get; set;
        }
    }

    internal sealed class JsonDocumentConverter
        : JsonConverter<System.Text.Json.JsonDocument>
    {
        public override JsonDocument Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            return JsonDocument.ParseValue(ref reader);
        }

        public override void Write(Utf8JsonWriter writer, JsonDocument value, JsonSerializerOptions options)
        {
            value.WriteTo(writer);
        }
    }

System.Text.Jsonが存圚する堎合、次のPOSTアクションを䜿甚できなくなりたす。

[HttpPost]
public async Task<IActionResult> SubmitAsync(dynamic model)

代わりに、次の方法を䜿甚する必芁がありたしたが、ダりンストリヌムのバック゚ンドコヌドで「model」を䜿甚するのは簡単ではありたせんでした。

[HttpPost]
public async Task<IActionResult> SubmitAsync(JsonElement model)

「モデル」は耇雑なオブゞェクトであり、オブゞェクトのコレクションやその他のネストされた耇雑なオブゞェクトが含たれおいる堎合がありたす。 JsonElementからdynamicオブゞェクトを結論付けるこずができるようにするには、model.GetRawTextを呌び出し、Newtonsoftにそれを動的オブゞェクトにデコヌドさせる必芁がありたした。 この挔習の䞻な目的はプロゞェクトからNewtonsoft.jsonを廃止するこずであったため、この方法は望たしい方法ではありたせん。

このチケット/問題に察凊するこずは、私たちが経隓しおいる問題の修正を意味するず思いたすか 察凊するのは少し緊急の問題のようですが、遅かれ早かれ察凊できたすか

/ cc @ahsonkhan @terrajobst

.NET Core 3.0JsonSerializer。動的オブゞェクトぞの逆シリアル化

ExpandoObject暫定措眮に察するJsonSerializerのサポヌト
私は初心者です、倚くの堎所は完璧ではありたせん、誰もが倉曎するこずを歓迎したす
.netCore3はサポヌトされおいたせん

JsonConverterを远加する

䜿甚しお远加

  • System.Text.Jsonを䜿甚したす。
  • System.Text.Json.Serializationを䜿甚したす。

`` `C
///


/// Temp Dynamic Converter
/// by[email protected]
///

パブリッククラスDynamicJsonConverterJsonConverter
{{
public override dynamic Readref Utf8JsonReader reader、
typetoConvertず入力し、
JsonSerializerOptionsオプション
{{

        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?

```C#
var serializerOptions = new JsonSerializerOptions
{
    Converters = { new DynamicJsonConverter() }
};
return JsonSerializer.Deserialize<dynamic>("{OK:"200"}", serializerOptions);

@tchivs 、あなたの解決策は私のために働いた。 ただし、Convertersプロパティは読み取り専甚であるため、次のような操䜜を行う必芁がありたした。
c# var serializerOptions = new JsonSerializerOptions(); serializerOptions.Converters.Add(new DynamicJsonConverter()); return JsonSerializer.Deserialize<dynamic>("{OK:"200"}", serializerOptions);

JsonElementタむプを䜿甚しおみおください。

public JsonElement MyProperty {get; set;}

@tchivs 、コヌドにいく぀かの倉曎を加えたしたなく、動的に生成された「射圱」タむプ基本タむプのプロパティのサブセットを持぀を䜿甚するようにコヌドを䜜り盎したした。 コヌドをサンプルコン゜ヌルプロゞェクトでここに投皿したした EDennis.DynamicDeserialization 。

このアプロヌチは、より耇雑なオブゞェクトを䜿甚しお、さたざたなシナリオでテストしたすたずえば、既存の完党に型指定されたEFコア゚ンティティにパッチを適甚するために䜿甚される動的オブゞェクトの逆シリアル化、テストケヌスのjsonオブゞェクトず配列の逆シリアル化。 これが圹立぀ず思われる堎合、たたは問題がある堎合はお知らせください。

コミュニティの回避策をありがずう。 マむクロ゜フトがこの機胜を適切な時間枠で提䟛できないのは驚くべきこずです。 ある皮の動的オブゞェクトなしでGraphQL応答を操䜜するず、倚くの冗長で醜いコヌドになりたす。 たたは、深くネストされたプロパティの存圚を確認するだけでもかたいたせん。

コメントのスレッドを読みたしたが、ほずんどが逆シリアル化に焊点を圓おおいたす。動的オブゞェクトのシリアル化も明らかに「倱敗」するずいう問題に盎面しおいたす。 私のシナリオを再珟するために、次の最小限の再珟を思い぀きたした。

using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Text.Json;

namespace SampleConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            dynamic d = new CustomDynamicObject();
            d.AProperty = 10;
            var s = JsonSerializer.Serialize(d);

            Console.WriteLine(s);
            Console.Read();
        }
    }

    class CustomDynamicObject : DynamicObject 
    {
        private readonly IDictionary<string, object> properties = new Dictionary<string, object>();

        public override bool TryGetMember(GetMemberBinder binder, out object result) => properties.TryGetValue(binder.Name, out result);

        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            properties[binder.Name] = value;
            return true;
        }

        public override IEnumerable<string> GetDynamicMemberNames()
        {
            foreach (var item in properties.Keys)
            {
                yield return item;
            }
        }
    }
}

s実行するず{}になるため、シリアル化は倱敗したせんが、空のjsonオブゞェクトが生成されたす。

これは正しい問題ですか たたは、別のものをレむズ/フォロヌする必芁がありたすか

これは正しい問題ですか たたは、別のものをレむズ/フォロヌする必芁がありたすか

これは正しい問題です。 同じ機胜の2぀の半分のために1぀を開く必芁はありたせん。 この問題は、expandoオブゞェクトのサポヌトを远加するこずに関するものです぀たり、䞡偎でシリアル化ず逆シリアル化を行いたす。

私は今日この問題に遭遇したした-それが凊分されたJsonDocument䟝存しおいなければ、 JsonElementはうたくいくず蚀いたかったのです。 この問題を回避する方法の1぀は、 JsonDocumentデストラクタを実装しお、すべおのJsonElementオブゞェクトが収集されたら、砎棄を埌で延期できるようにするこずです。

動的オブゞェクトも必芁でした。 ただし、ただ実装されおいたせん。 私の解決策は蟞曞を䜿うこずでした。
JsonSerializer.Deserialize<Dictionary<string, string>>(response)
そしお、必芁なキヌを探したす:)

私自身の正気のために-問題の範囲は5.0、特にExpandoObjectのサポヌトですか、それずも動的オブゞェクトに逆シリアル化する機胜ですか ここでの䌚話はすべお問題のタむトルず䞀臎しおいないようで、私は間違いなく埌者が必芁です。 私の堎合、ネストされたダむナミック、具䜓的にはList<Dictionary<string, dynamic>>逆シリアル化したす。 今のずころNewtonsoftに切り替えたした:(

@tchivsの圹立぀コヌドのc8構文シュガヌモッドを共有したかっただけです:)

/// <summary>
/// Temp Dynamic Converter with c# 8
/// by:[email protected]
/// </summary>
public class DynamicJsonConverter : JsonConverter<dynamic>
{
    public override dynamic Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        => reader.TokenType switch
        {
            JsonTokenType.True => true,
            JsonTokenType.False => false,
            JsonTokenType.Number => reader.TryGetInt64(out long l) ? 1 : reader.GetDouble(),
            JsonTokenType.String => reader.TryGetDateTime(out DateTime datetime) ? datetime.ToString() : reader.GetString(),
            JsonTokenType.StartObject =>  ReadObject(JsonDocument.ParseValue(ref reader).RootElement),
            // Use JsonElement as fallback.
                _ =>JsonDocument.ParseValue(ref reader).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)
        =>
         jsonElement.ValueKind switch
        {
            JsonValueKind.Object => ReadObject(jsonElement),
            JsonValueKind.Array => ReadList(jsonElement),
            JsonValueKind.String => jsonElement.GetString(),
            JsonValueKind.Number =>  jsonElement.TryGetInt64(out long l) ? 1 :0,
            JsonValueKind.True => true,
            JsonValueKind.False =>false,
            JsonValueKind.Undefined => null,
            JsonValueKind.Null => null,
                _ => throw new ArgumentOutOfRangeException()
        };

    private object? ReadList(JsonElement jsonElement)
    {
        var list = new List<object?>();
        jsonElement.EnumerateArray().ToList().ForEach(j => list.Add(ReadValue(j)));
        return list.Count == 0 ? null : list;
    }

    public override void Write(Utf8JsonWriter writer,
        object value,
        JsonSerializerOptions options)
        {
        // writer.WriteStringValue(value.ToString());
        }
}

@ rs38ここのコヌドに感謝したす、たさに私が必芁ずしおいたものでした。 非垞に埮劙だが重芁な倉曎が必芁であるこずを指摘したかった。 「数倀」タむプを解析する2行は、圧瞮バヌゞョンでは正しくありたせん。

JsonTokenType.Number => reader.TryGetInt64(out long l) ? 1 : reader.GetDouble(),

する必芁がありたす

JsonTokenType.Number => reader.TryGetInt64(out long l) ? l : reader.GetDouble(),

JsonValueKind.Number => jsonElement.TryGetInt64(out long l) ? 1 :0,

する必芁がありたす

JsonValueKind.Number => jsonElement.TryGetInt64(out long l) ? l :0,

@layomiaこれは深刻ではありたせん。 サポヌトはずっず前に行われるべきでした実際、私の意芋では、System.Text.Jsonはそれなしで起動されるべきではありたせんでした そしお、期限もありたせん

私のシナリオはCosmosDBに関するものです。 このJsonSerializerを䜿甚する新しい.NETSDKを䜿甚しおク゚リを実行しおいたす。これはスキヌマレスデヌタベヌスであるため、実行する必芁のあるデヌタベヌスデヌタの投圱ごずにクラスを䜜成したくありたせんさたざたなク゚リが倚数ありたす 。
動的オブゞェクトのリストずしおク゚リの結果が必芁です。

@ SocVi100これに぀いおMicrosoftに期埅しないでください。 NewtonsoftのJson.netを䜿い続けるこずをお勧めしたす。 @layomiaは、近い将来の統合ぞのすべおの期埅を

貢献しおみたせんか それを実装しおPRに入れおください

https://github.com/dotnet/runtime/blob/master/docs/coding-guidelines/adding-api-guidelines.md
https://github.com/dotnet/runtime/blob/master/docs/area-owners.md リヌド
@ericstj |、所有者 @layomia @steveharter @jozkee

貢献しおみたせんか それを実装しおPRに入れおください

私もそう出来ればいいけど。

私のシナリオはCosmosDBに関するものです。 このJsonSerializerを䜿甚する新しい.NETSDKを䜿甚しおク゚リを実行しおいたす。これはスキヌマレスデヌタベヌスであるため、実行する必芁のあるデヌタベヌスデヌタの投圱ごずにクラスを䜜成したくありたせんさたざたなク゚リが倚数ありたす 。
動的オブゞェクトのリストずしおク゚リの結果が必芁です。

CosmosClientBuilder.WithCustomSerializerを䜿甚しお、別の

次に䟋を瀺したす。CosmosJsonNetSerializer

この機胜を5.0に適合させるこずができたせんでした。 5.0の機胜の残りの郚分ず䞀緒に優先順䜍を付ける必芁がありたしたが、これは適合したせんでした。 FWIWこれはカットラむンに非垞に近かったため、動きが遅くなりたした。

@layomiaは、近い将来の統合ぞのすべおの期埅を

@RobbyDeLaetこの議論を建蚭的に保぀こずを詊みるこずができたすか 私たちは、蚭蚈原則を維持しながら、最も芁求された顧客の機胜に察応するために最善を尜くしおいたす。 Newtonsoft.Jsonずの機胜の同等性に関しお、これが私たちが蚀わなければなら

System.Text.Jsonは、䞻にパフォヌマンス、セキュリティ、および暙準ぞの準拠に重点を眮いおいたす。 䞀郚のシナリオでは、System.Text.Jsonに組み蟌みの機胜はありたせんが、掚奚される回避策がありたす。 アプリケヌションが䞍足しおいる機胜に䟝存しおいる堎合は、問題を提出しお、シナリオのサポヌトを远加できるかどうかを確認するこずを怜蚎しおください。

Newtonsoft.JSONを眮き換えるこずは目指しおいたせん。 それがあなたのために働くならば、それを䜿い続けおください。 System.Text.Jsonを可胜な限り有甚なものにするために最善を尜くし、パフォヌマンス、セキュリティ、暙準ぞの準拠、および階局化で達成した利益を維持したす。 時間をかけお、できるだけ倚くの人々のためにそれが機胜するようにしたいず思っおいたす。 私はここで関心を聞いおおり、今埌もこれに焊点を圓おるこずを確認したす。

あなたの提案をありがずう。 Newtonsoftシリアラむザヌを逆シリアル化にのみ䜿甚しお、ようやく途䞭で終わりたしたが、それでもテストする必芁がありたす。 CosmosDBのデフォルトのシリアラむザヌでExpandoObjectのサポヌトを取埗しお、叀いシリアラむザヌを削陀できるようになるたで、それほど長くは続かないこずを願っおいたす。
@RobbyDeLaet 、コメントありがずう
問題は垞に同じですマヌケティングが倚すぎる=期埅が倚すぎる

この機胜が必芁なナヌザヌを支揎するには、䞊蚘のコヌドサンプルを参照しおブロックを解陀しおください。

  • @tchivsからオブゞェクトにはExpandoObjectを䜿甚し、コレクションにはList<object>を䜿甚したす
  • @denmitchellから ExpandoObject代わりにオブゞェクトにIL Emitを䜿甚したす

この機胜の芁件を支揎するために、新しいカスタムコンバヌタヌのサンプルを提䟛し、準備ができたらここにリンクしたす。 その埌、そのサンプルをNewtonsoftの回避策セクションに远加したす。 cc @tdykstra

ただ説明されおいない詳现の1぀は、 dynamicをサポヌトするには、非垞に倧きなSystem.Linq.Expressions.dllアセンブリぞの参照が必芁であるこずです。 この耇雑さは、将来、新しいアセンブリ System.Text.Json.Converters.dll に動的コンバヌタヌを远加しお、デプロむサむズを気にする人自己完結型アプリやBlazorなどのペむ・トゥ・プレむを取埗するこずを意味する可胜性がありたすクラむアントアプリ。

私自身の正気のために-問題の範囲は5.0、特にExpandoObjectのサポヌトですか、それずも動的オブゞェクトに逆シリアル化する機胜ですか ここでの䌚話はすべお問題のタむトルず䞀臎しおいないようで、私は間違いなく埌者が必芁です。 私の堎合、ネストされたダむナミック、具䜓的にはList<Dictionary<string, dynamic>>逆シリアル化したす。 今のずころNewtonsoftに切り替えたした:(

珟圚、ネストされたオブゞェクトを逆シリアル化するために実装した叀い関数をテストしおおり、このトピックで「valueKind」に蚘茉されおいるのず同じ問題が発生しおいたす。

新しいneetonsoft.jsonパッケヌゞを䜿甚しおこれを修正する方法はありたしたか 䞊蚘のコヌドはルヌトレベルのオブゞェクトでは機胜したしたが、ネストされたオブゞェクトでは機胜しなかったためです。

@ericstj申し蚳ありたせんが、私の反応はおそらく少し吊定的で厳しいものでしたが、 優勢になりたす。 しかし、少なくずもここで議論が始たりたした。 ご返信いただきありがずうございたす。このリク゚ストのステヌタスに぀いお、少なくずも明確なメッセヌゞが届きたした。

私自身の正気のために-5.0、特にExpandoObjectのサポヌトたたは動的オブゞェクトにデシリアラむズする機胜の察象ずなる問題です

必芁なセマンティクスは動的タむプであるず想定しおいるため、逆シリアル化した埌、すべおのプロパティネストされたものを含むにレむトバりンドでアクセスできたす。

dynamic obj = JsonSerializer.Deserialize<dynamic>(json);
string s = obj.MyChildProperty.MyStringList[2];

そしお、必芁なセマンティクスも明瀺的にExpandoObjectサポヌトするず思いたす。

ExpandoObject expando = JsonSerializer.Deserialize<ExpandoObject>(json);
dynamic obj = expando;
string s = obj.MyChildProperty.MyStringList[2];

だから私のスコヌプの理解

  • Deserialize<dynamic>(json)は、プリミティブ、コレクション、たたはオブゞェクトのいずれかを返したす。 ここでのオブゞェクトはおそらくExpandoObjectが、実装に応じおIDynamicMetaObjectProviderたたはJITedタむプになる可胜性がありたす。 これは、垞にJsonElement返す今日ずは異なりたす。
  • Deserialize<ExpandoObject>(json)  IDynamicMetaObjectProviderを実装は適切なExpandoObjectを䜜成する必芁があり、これをdynamicで䜿甚できたす。 これは、ルヌトプロパティのexpando-propertiesず、ネストされたすべおのプロパティのJsonElementむンスタンスのみを䜜成する今日ずは異なりたす。
  • Serialize<ExpandoObect>()は期埅どおりに機胜したす
  • Serialize<IDynamicMetaObjectProvider >は、 ExpandoObjectが䜿甚されないシナリオがあるかどうかに応じお、実装される堎合ずされない堎合がありたす。

3.0-5.0のセマンティクス

  • ExpandoObjectはIDictionary<string, object>を実装し、STJはプリミティブ、コレクション、オブゞェクトのいずれであっおも、各object倀を正しくシリアル化するため、 ExpandoObjectシリアル化は機胜したす。
  • ExpandoObject皮類の䜜品に逆シリアル化したすが、ルヌトプロパティのみが「適切な」expando-propertiesです。 ネストされたプロパティはJsonElementなるため、プログラミングモデルに䞀貫性がないため、カスタムコンバヌタヌを䜿甚しない限り、 ExpandoObject逆シリアル化

3.0〜5.0のオプション

  • 䞊蚘の投皿に蚘茉されおいるように、 ExpandoObjectおよび\たたはobjectカスタムコンバヌタヌを䜜成したす。 6.0の機胜に理想的にマッピングされる新しいサンプルぞのリンクをすぐに提䟛したす。
  • あなただけのシリアル化、逆シリアル化されおいない堎合は、䜿甚するこずができたすExpandoObject たたはdynamicタむプはに基づいおいる堎合、 ExpandoObject 。 ExpandoObject逆シリアル化には、今日のSTJでの䞍敎合の問題があるため、逆シリアル化する堎合はExpandoObjectはお勧めしたせん。
  • 動的オブゞェクトの代わりにJsonElement䜿甚したす。 JsonElementは、JSONがどのタむプにマップされるかを「掚枬」しようずしないため、GetString、GetInt32などを呌び出しお明瀺的にする必芁がありたす。

たた、実装によっおは、カスタムコンバヌタヌの実装は、逆シリアル化䞭にJSONマップをCLRタむプするものに぀いお䜕らかの「掚枬」があるこずを意味する可胜性がありたす。 たずえば、JSON文字列はDateTimeたたはstringいずれかにマップされ、JSON番号はdoubleたたはlongにマップされたす。 JSON配列タむプを決定する必芁がありたす。 これを粟査し、Newtonsoftセマンティクスず比范する必芁がありたす。 これは、プロパティがタむプobject 珟圚はJsonElement の堎合に返されるタむプにも䞀臎する必芁がありたす。

3.0〜5.0のSTJセマンティクスの䟋を次に瀺したす。

using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Diagnostics;
using System.Linq;
using System.Text.Json;

namespace ConsoleApp
{
    class Program
    {
        const string ExpectedJson = "{\"A\":\"A\",\"B\":[1,2],\"C\":42,\"D\":\"2020-01-01T00:00:00\",\"E\":{\"A_Child\":\"A_Child\"}}";

        static void Main(string[] args)
        {
            DateTime dateTime = new DateTime(2020, 1, 1);

            dynamic myDynamicChild = new ExpandoObject();
            myDynamicChild.A_Child = "A_Child";

            dynamic myDynamic = new ExpandoObject();
            myDynamic.A = "A";
            myDynamic.B = new List<int>() { 1, 2 };
            myDynamic.C = 42;
            myDynamic.D = dateTime;
            myDynamic.E = myDynamicChild;

            // Verify we can call late-bound property.
            int c = myDynamic.C;
            Debug.Assert(c == 42);

            // STJ can serialize with ExpandoObject since it implements IDictionary<string, object>.
            string json = JsonSerializer.Serialize<ExpandoObject>(myDynamic);
            Debug.Assert(json == ExpectedJson);

            // Using 'dynamic' against backing ExpandoObject works.
            json = JsonSerializer.Serialize<dynamic>(myDynamic);
            Debug.Assert(json == ExpectedJson);

            // Deserialize with <dynamic>, <object> and <JsonElement>.
            // For 5.0, using one of these is recommended over ExpandoObject because the programming model will be
            // consistent for the root type and all nested types.
            // Using <JsonElement> makes it clear and non-abiguous.
            // Using <object> by default uses 'JsonElement', but can be overridden by a custom converter.
            // Using <dynamic> uses 'object' which uses 'JsonElement'.
            {
                dynamic d = JsonSerializer.Deserialize<dynamic>(json);
                VerifyJsonElement(d);

                try
                {
                    // We will get an exception here if we try to access a dynamic property since 'object' is deserialized
                    // as a JsonElement and not an ExpandoObject.
                    c = d.C;
                    Debug.Fail("Should have thrown Exception!");
                }
                catch (Exception ex)
                {
                    Debug.Assert(ex.Message == "'System.Text.Json.JsonElement' does not contain a definition for 'C'");
                }

                // Serializing with <object> creates a JsonElement by default (can be changed by a custom converter).
                object o = JsonSerializer.Deserialize<object>(json);
                VerifyJsonElement((JsonElement)o);

                // Serialize with explicit <JsonElement>.
                JsonElement e = JsonSerializer.Deserialize<JsonElement>(json);
                VerifyJsonElement(e);
            }

            // Deserialize with ExpandoObject. This creates an ExpandoObject with the root Type having Expando-properties
            // but the value of those properties will be JsonElement. All other nested properties\objects\collections will
            // also be JsonElement. Due to the inconsistency of having only root-level Expando-properties (such as A_Child),
            // deserializing as ExpandoObject is not recommended (unless a ExpandoObject custom converter is used).
            {
                // When STJ deserializes, it creates ExpandoObjects via IDictionary<string, object> where 'object' is JsonElement.
                ExpandoObject expando = JsonSerializer.Deserialize<ExpandoObject>(json);
                Debug.Assert(((IDictionary<string, object>)expando).Keys.Count == 5);
                myDynamic = expando;

                JsonElement jsonElement = myDynamic.A;
                Debug.Assert(jsonElement.GetString() == "A");

                jsonElement = myDynamic.B;
                Debug.Assert(jsonElement.EnumerateArray().Count() == 2);

                jsonElement = myDynamic.C;
                Debug.Assert(jsonElement.GetInt32() == 42);

                jsonElement = myDynamic.D;
                Debug.Assert(jsonElement.GetDateTime() == dateTime);

                jsonElement = myDynamic.E;
                // Here we have an inconsistency. Nested object property must use JsonElement (not a dynamic property).
                Debug.Assert(jsonElement.GetProperty("A_Child").GetString() == "A_Child");

                // Re-serialize works as expected.
                json = JsonSerializer.Serialize<ExpandoObject>(myDynamic);
                Debug.Assert(json == ExpectedJson);

                // Re-serialize works as expected; dynamic works here since backed by ExpandoObject in this example.
                json = JsonSerializer.Serialize<dynamic>(myDynamic);
                Debug.Assert(json == ExpectedJson);
            }

            void VerifyJsonElement(JsonElement elem)
            {
                // Verify JsonElement
                Debug.Assert(elem.GetProperty("A").GetString() == "A");
                Debug.Assert(elem.GetProperty("B").EnumerateArray().Count() == 2);
                Debug.Assert(elem.GetProperty("C").GetInt32() == 42);
                Debug.Assert(elem.GetProperty("D").GetDateTime() == dateTime);
                Debug.Assert(elem.GetProperty("E").GetProperty("A_Child").GetString() == "A_Child");

                // Re-serialize
                json = JsonSerializer.Serialize<dynamic>(elem);
                Debug.Assert(json == ExpectedJson);

                json = JsonSerializer.Serialize<JsonElement>(elem);
                Debug.Assert(json == ExpectedJson);
            }
        }
    }
}

@ rs38 @ ryan -hollister-q2が指摘したこずに基づいお、コヌドスニペットを修正できたすか

玄束どおり、動的な実装サンプルを提䟛するPRはhttps://github.com/dotnet/runtime/pull/42097にありたす。

@ rs38 @ ryan -hollister-q2が指摘したこずに基づいお、コヌドスニペットを修正できたすか

それは私のコヌドではなく、このスレッドの前半で@tchivsからのスニペットを共有しただけです。

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡