簡體   English   中英

在創建JsonObjectContract時禁止$ type

[英]Suppress $type at the creation of the JsonObjectContract

我試圖在Json.NET中強制抑制一些特定的$ type輸出(同時保留其他輸出)。 它們在我的應用程序中是不必要的。 Json.NET源代碼顯示了這一點:

private bool ShouldWriteType(...)
{
  TypeNameHandling resolvedTypeNameHandling =
    ((member != null) ? member.TypeNameHandling : null)
    ?? ((containerProperty != null) ? containerProperty.ItemTypeNameHandling : null)
    ?? ((containerContract != null) ? containerContract.ItemTypeNameHandling : null)
    ?? Serializer._typeNameHandling;

這讓我認為我可以通過在容器協定中設置ItemTypeNameHandling來覆蓋序列化程序設置。 ,,它不適用於數組。 我嘗試重寫該方法以獲取數組協定,但是那里的設置會影響數組中的每個項目。 那不是我想要的 (然后SignalR在對象數組中發送所有方法參數。)這是我的完整演示代碼,在這里我試圖弄清楚如何在輸出中保留A類型,但抑制B類型(以及所有sealed類)。 如何覆蓋合同解析器以正確執行此操作?

using System;
using System.Diagnostics;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

namespace DemoBadTypeInclusion
{
    class A { public int P1 { get; set; } }

    // this attribute doesn't work and I don't want to have to reference Json.NET in my POCO
    //[JsonObject(ItemTypeNameHandling = TypeNameHandling.None)]
    sealed class B { public int P2 { get; set; } }

    internal class DtoContractResolver : DefaultContractResolver
    {
        protected override JsonObjectContract CreateObjectContract(Type objectType)
        {
            var contract = base.CreateObjectContract(objectType);
            if (objectType.IsSealed && objectType.BaseType == typeof(object))
            {
                contract.ItemTypeNameHandling = TypeNameHandling.None;
            }
            return contract;
        }
    }

    class Program
    {
        static void Main()
        {
            var objs = new object[] {new A {P1 = 3}, new B {P2 = 4}};

            var settings = new JsonSerializerSettings
            {
                TypeNameHandling = TypeNameHandling.Auto,
                NullValueHandling = NullValueHandling.Ignore,
                TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple,
                ContractResolver = new DtoContractResolver(),
            };

            var json = JsonConvert.SerializeObject(objs, settings);
            Console.WriteLine(json);

            if (Debugger.IsAttached)
                Console.ReadKey();
        }
    }
}

更新:在進一步研究了Json.NET代碼之后,似乎來自SerializeList這一行是我麻煩的根源:

JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value);

我想要回退值( GetContractSafe )。 有誰知道如何使FinalItemContract null?

如果取消對對象Array的一種類型引用,則將使Array不可反序列化。 因此,您可以取消對Array的所有類型引用。

僅抑制對象數組的類型引用

protected override JsonArrayContract CreateArrayContract(Type objectType)
{
            var c = base.CreateArrayContract(objectType);

            if(objectType == typeof(Object[]))
                c.ItemTypeNameHandling = TypeNameHandling.None;

            return c;
}

如果您不需要反序列化回原始對象,只需設置

new JsonSerializerSettings
{
  TypeNameHandling = TypeNameHandling.None,
  ...
};

我知道這不是一個確切的答案,但是我看不到有任何使用組件來標識對象數組的某些元素以進行反序列化的類型。 所以我認為,這就是為什么json.net不支持它的原因

畢竟,這里是一種解決方法,它僅抑制一種類型:

static void Main()
        {
            var objs = new object[] { new A { P1 = 3 }, new B { P2 = 4 } };

            var settings = new JsonSerializerSettings
            {
                TypeNameHandling = TypeNameHandling.Objects,
                NullValueHandling = NullValueHandling.Ignore,
                TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple,
                ContractResolver = new DtoContractResolver(),
            };


            var serial = JsonSerializer.Create(settings);

            var jsonArray = new JArray();


            foreach (var obj in objs)
            {
                if (obj != null && obj.GetType().IsSealed && obj.GetType().BaseType == typeof(object))
                    serial.TypeNameHandling = TypeNameHandling.None;
                else
                    serial.TypeNameHandling = TypeNameHandling.Objects;

                jsonArray.Add(JObject.FromObject(obj, serial));
            }

            var json = jsonArray.ToString(Formatting.None);
            Console.WriteLine(json);

            if (Debugger.IsAttached)
                Console.ReadKey();
        }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM