問題:
JSON.Net 内で [JsonConvert] 属性を使用して複雑なオブジェクトをフラット化された JSON にシリアル化すると、StackOverflowException
.
根本原因:
提供されている FJson
カスタム コンバーターは、再帰的メソッド (WriteJson
) を使用してオブジェクト グラフを JSON ライターに書き込みます。この再帰的なアプローチには、さまざまなシナリオに対する十分な保護手段が欠けており、無限ループやスタック オーバーフロー エラーが発生する可能性があります。 これらのシナリオには次のものが含まれます:
ShouldSerialize*()
メソッド: プロパティのシリアル化を決定するカスタム メソッドは、意図しない再帰を引き起こす可能性があります。解決策:
この StackOverflowException
を解決する鍵は、WriteJson
コンバーターの FJson
メソッドを強化して、これらのエッジ ケースに対処することにあります。 改訂された WriteJson
メソッドを以下に示します。
<code class="language-csharp">public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (ReferenceEquals(value, null)) { writer.WriteNull(); return; } var contract = (JsonObjectContract)serializer .ContractResolver .ResolveContract(value.GetType()); writer.WriteStartObject(); foreach (var property in contract.Properties) { if (property.Ignored) continue; if (!ShouldSerialize(property, value)) continue; var propertyName = property.PropertyName; var propertyValue = property.ValueProvider.GetValue(value); writer.WritePropertyName(propertyName); if (property.Converter != null && property.Converter.CanWrite) { property.Converter.WriteJson(writer, propertyValue, serializer); } else { serializer.Serialize(writer, propertyValue); } } writer.WriteEndObject(); } private static bool ShouldSerialize(JsonProperty property, object instance) { return property.ShouldSerialize == null || property.ShouldSerialize(instance); }</code>
この改善されたバージョンは、null 値を明示的に処理し、カスタム ShouldSerialize
メソッドを効果的に管理するための ShouldSerialize*()
ヘルパー メソッドを組み込み、それによって StackOverflowException
につながる無限再帰を防ぎます。 また、必要に応じてシリアル化を既存のコンバーターに正しく委任します。 この改訂されたアプローチでは、[JsonConvert] 属性と使用した場合にスタック オーバーフロー エラーが発生することなく、複雑なオブジェクトを確実にシリアル化できるようになります。
以上が複雑なオブジェクトをシリアル化するときに、JsonConvert 属性によって StackOverflowException が発生するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。