Làm thế nào để loại trừ tài sản khỏi Json serialization


234

Tôi có một lớp DTO mà tôi nối tiếp

Json.Serialize(MyClass)

Làm thế nào tôi có thể loại trừ một tài sản công cộng của nó?

(Nó phải được công khai, vì tôi sử dụng nó trong mã của mình ở một nơi khác)


4
Bạn sử dụng khung nối tiếp nào?
Pavel Gatilov

37
IgnoreDataMember ScriptIgnore JsonIgnoretùy thuộc vào bộ nối tiếp bạn sử dụng
LB

3
cũng đáng chú ý là thuộc tính [NonSerialized], chỉ áp dụng cho các trường (không phải thuộc tính), nhưng mặt khác có tác dụng tương tự như JsonIgnore.
Triynko

Nhận xét của Trynko rất hữu ích .... nếu bạn sử dụng IgnoreDataMember trên một trường sẽ không có lỗi, nhưng nó sẽ không được áp dụng.
Tillito

Câu trả lời:


147

Nếu bạn đang sử dụng System.Web.Script.Serializationtrong .NET framework, bạn có thể đặt một ScriptIgnorethuộc tính cho các thành viên không nên được tuần tự hóa. Xem ví dụ lấy từ đây :

Xem xét trường hợp (đơn giản hóa) sau:

public class User {
    public int Id { get; set; }
    public string Name { get; set; }
    [ScriptIgnore]
    public bool IsComplete
    {
        get { return Id > 0 && !string.IsNullOrEmpty(Name); }
    } 
} 

Trong trường hợp này, chỉ các thuộc tính Id và Tên sẽ được tuần tự hóa, do đó, đối tượng JSON kết quả sẽ trông như thế này:

{ Id: 3, Name: 'Test User' }

Tái bút Đừng quên thêm một tham chiếu đến " System.Web.Extensions" để làm việc này


10
Tôi tìm thấy ScriptIgnoretrong System.Web.Script.Serializationkhông gian tên.
Sorangwala Abbasali

354

Nếu bạn đang sử dụng thuộc tính Json.Net[JsonIgnore] sẽ chỉ cần bỏ qua trường / thuộc tính trong khi tuần tự hóa hoặc giải tuần tự hóa.

public class Car
{
  // included in JSON
  public string Model { get; set; }
  public DateTime Year { get; set; }
  public List<string> Features { get; set; }

  // ignored
  [JsonIgnore]
  public DateTime LastModified { get; set; }
}

Hoặc bạn có thể sử dụng thuộc tính DataContract và DataMember để chọn lọc tuần tự hóa / deserialize thuộc tính / trường.

[DataContract]
public class Computer
{
  // included in JSON
  [DataMember]
  public string Name { get; set; }
  [DataMember]
  public decimal SalePrice { get; set; }

  // ignored
  public string Manufacture { get; set; }
  public int StockCount { get; set; }
  public decimal WholeSalePrice { get; set; }
  public DateTime NextShipmentDate { get; set; }
}

Tham khảo http://james.newtonking.com/archive/2009/10/23/ffic-json-with-json-net-reducing-serialized-json-size để biết thêm chi tiết


37
Nếu tôi là OP, tôi thích câu trả lời này hơn giải pháp [ScriptIgnore] đã chọn. Chủ yếu là do sự phù hợp của một giải pháp Json nên một vấn đề Json. Tại sao liên quan đến System.Web.Extensions khi thư viện bạn đang sử dụng cung cấp giải pháp? IMHO tốt nhất tuyệt đối là thuộc tính [IgnoreDataMember], vì System.R.78.Serialization phải tương thích với mọi serializer nếu bạn muốn trao đổi Json.
Steve H.

IgnoreDataMemberkhông hoạt động với JsonResultserializer mặc định .
hendryanw

1
NewtonSoft chỉ giúp tôi đầy đủ. Nó làm cho json của tôi trông sạch sẽ mà không có bất kỳ thuộc tính lộn xộn nào được đưa vào từ các mô hình của tôi chỉ dành cho phụ trợ.
Sorangwala Abbasali

1
@JC Raja Làm thế nào tôi có thể bỏ qua tài sản trong khi khử muối chỉ khi tài sản này là null
user123456

1
[NewtonSoft.Json] Tôi chỉ muốn bỏ qua việc xê-ri hóa. Vậy thì giải pháp nào cho việc này?
Trương Quốc Khánh

31

Bạn có thể sử dụng [ScriptIgnore]:

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    [ScriptIgnore]
    public bool IsComplete
    {
        get { return Id > 0 && !string.IsNullOrEmpty(Name); }
    }
}

Tham khảo tại đây

Trong trường hợp này, Id và sau đó tên sẽ chỉ được nối tiếp


1
URL trong câu trả lời của bạn bị hỏng. Là [ScriptIgnore]những gì nên được sử dụng trên tài sản nếu bộ điều khiển của bạn đang sử dụng Bộ điều khiển MVC cơ sở return Json(...?
Don Cheadle

2
Tôi biết đó là một nhận xét cũ, nhưng vâng, sử dụng [ScriptIgnore]trong Bộ điều khiển MVC. Mặc dù được cảnh báo, nếu bạn đang sử dụng SignalR , thì bạn cũng nên sử dụng [JsonIgnore].
Sam

21

Xin lỗi tôi quyết định viết một câu trả lời khác vì không có câu trả lời nào khác có thể sao chép đủ.

Nếu bạn không muốn trang trí các thuộc tính với một số thuộc tính hoặc nếu bạn không có quyền truy cập vào lớp hoặc nếu bạn muốn quyết định tuần tự hóa cái gì trong thời gian chạy, v.v. thì đây là cách bạn làm điều đó trong Newtonsoft.Json

//short helper class to ignore some properties from serialization
public class IgnorePropertiesResolver : DefaultContractResolver
{
    private IEnumerable<string> _propsToIgnore;
    public IgnorePropertiesResolver(IEnumerable<string> propNamesToIgnore)
    {
        _propsToIgnore = propNamesToIgnore;
    }
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);
        property.ShouldSerialize = (x) => { return !_propsToIgnore.Contains(property.PropertyName); };
        return property;
    }
}

Sử dụng

JsonConvert.SerializeObject(YourObject, new JsonSerializerSettings()
    { ContractResolver = new IgnorePropertiesResolver(new[] { "Prop1", "Prop2" }) };);

Tôi đã xuất bản mã ở đây trong trường hợp bất cứ ai muốn thêm bất cứ điều gì

https://github.com/jitbit/JsonIgnoreProps

CẬP NHẬT QUAN TRỌNG: đảm bảo bạn lưu trữ ContractResolverđối tượng nếu bạn quyết định sử dụng câu trả lời này, nếu không hiệu suất có thể bị ảnh hưởng.


15

Nếu bạn không quan tâm đến việc phải trang trí mã với các thuộc tính như tôi, đặc biệt khi bạn không thể nói vào thời gian biên dịch, điều gì sẽ xảy ra ở đây là giải pháp của tôi.

Sử dụng Trình tuần tự Javascript

    public static class JsonSerializerExtensions
    {
        public static string ToJsonString(this object target,bool ignoreNulls = true)
        {
            var javaScriptSerializer = new JavaScriptSerializer();
            if(ignoreNulls)
            {
                javaScriptSerializer.RegisterConverters(new[] { new PropertyExclusionConverter(target.GetType(), true) });
            }
            return javaScriptSerializer.Serialize(target);
        }

        public static string ToJsonString(this object target, Dictionary<Type, List<string>> ignore, bool ignoreNulls = true)
        {
            var javaScriptSerializer = new JavaScriptSerializer();
            foreach (var key in ignore.Keys)
            {
                javaScriptSerializer.RegisterConverters(new[] { new PropertyExclusionConverter(key, ignore[key], ignoreNulls) });
            }
            return javaScriptSerializer.Serialize(target);
        }
    }


public class PropertyExclusionConverter : JavaScriptConverter
    {
        private readonly List<string> propertiesToIgnore;
        private readonly Type type;
        private readonly bool ignoreNulls;

        public PropertyExclusionConverter(Type type, List<string> propertiesToIgnore, bool ignoreNulls)
        {
            this.ignoreNulls = ignoreNulls;
            this.type = type;
            this.propertiesToIgnore = propertiesToIgnore ?? new List<string>();
        }

        public PropertyExclusionConverter(Type type, bool ignoreNulls)
            : this(type, null, ignoreNulls){}

        public override IEnumerable<Type> SupportedTypes
        {
            get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { this.type })); }
        }

        public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
        {
            var result = new Dictionary<string, object>();
            if (obj == null)
            {
                return result;
            }
            var properties = obj.GetType().GetProperties();
            foreach (var propertyInfo in properties)
            {
                if (!this.propertiesToIgnore.Contains(propertyInfo.Name))
                {
                    if(this.ignoreNulls && propertyInfo.GetValue(obj, null) == null)
                    {
                         continue;
                    }
                    result.Add(propertyInfo.Name, propertyInfo.GetValue(obj, null));
                }
            }
            return result;
        }

        public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
        {
            throw new NotImplementedException(); //Converter is currently only used for ignoring properties on serialization
        }
    }

1
Một thay đổi nhỏ trong logic và PropertyExclusionConvertercó thể được biến thành a PropertyInclusionConverter.
Zarepheth

điều này thật tuyệt vời
SaiKiran Mandhala 7/12/2016

Một vấn đề tiềm ẩn với điều này là nó phải thực hiện công việc khớp tên và loại trừ lặp đi lặp lại mỗi lần một đối tượng được tuần tự hóa. Tuy nhiên, sau khi được biên dịch, các thuộc tính của một loại sẽ không thay đổi - bạn nên thực hiện tính toán trước này, theo từng loại, các tên cần được đưa vào và chỉ sử dụng lại danh sách trên mỗi hàng. Đối với một công việc tuần tự hóa JSON rất lớn, bộ nhớ đệm có thể tạo ra sự khác biệt đáng chú ý trong hiệu suất.
ErikE

9

Nếu bạn đang sử dụng System.Text.Jsonthì bạn có thể sử dụng [JsonIgnore].
FQ:System.Text.Json.Serialization.JsonIgnoreAttribute

Tài liệu chính thức của Microsoft: JsonIgnoreAttribution

Như đã nêu ở đây :

Thư viện được tích hợp sẵn như là một phần của khung chia sẻ .NET Core 3.0.
Đối với các khung mục tiêu khác, hãy cài đặt gói System.Text.Json NuGet. Gói hỗ trợ:

  • .NET Standard 2.0 và các phiên bản mới hơn
  • .NET Framework 4.6.1 và các phiên bản mới hơn
  • .NET Core 2.0, 2.1 và 2.2

0

Bạn cũng có thể sử dụng [NonSerialized]thuộc tính

[Serializable]
public struct MySerializableStruct
{
    [NonSerialized]
    public string hiddenField;
    public string normalField;
}

Từ các tài liệu MS :

Chỉ ra rằng một trường của một lớp tuần tự hóa không nên được tuần tự hóa. Lớp này không thể được thừa kế.


Nếu bạn đang sử dụng Unity chẳng hạn ( điều này không chỉ dành cho Unity ) thì điều này hoạt động vớiUnityEngine.JsonUtility

using UnityEngine;

MySerializableStruct mss = new MySerializableStruct 
{ 
    hiddenField = "foo", 
    normalField = "bar" 
};
Debug.Log(JsonUtility.ToJson(mss)); // result: {"normalField":"bar"}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.