json.net을 사용하여 null 인 경우 클래스의 속성을 무시하는 방법


529

Json.NET 을 사용하여 클래스를 JSON으로 직렬화하고 있습니다.

나는 이런 수업을 가지고있다 :

class Test1
{
    [JsonProperty("id")]
    public string ID { get; set; }
    [JsonProperty("label")]
    public string Label { get; set; }
    [JsonProperty("url")]
    public string URL { get; set; }
    [JsonProperty("item")]
    public List<Test2> Test2List { get; set; }
}

is 일 때만 JsonIgnore()속성에 Test2List속성 을 추가하고 싶습니다 . null이 아닌 경우 json에 포함시키고 싶습니다.Test2Listnull

답변:


685

James Newton King에 따르면 : JavaScriptConvert를 사용하지 않고 직접 serializer를 만드는 경우 무시하도록 설정할 수 있는 NullValueHandling속성 이 있습니다.

샘플은 다음과 같습니다.

JsonSerializer _jsonWriter = new JsonSerializer {
                                 NullValueHandling = NullValueHandling.Ignore
                             };

또는 @amit에서 제안한대로

JsonConvert.SerializeObject(myObject, 
                            Newtonsoft.Json.Formatting.None, 
                            new JsonSerializerSettings { 
                                NullValueHandling = NullValueHandling.Ignore
                            });

159
이것은 작동합니다 : JsonConvert.SerializeObject (myObject, Newtonsoft.Json.Formatting.None, new JsonSerializerSettings {NullValueHandling = NullValueHandling.Ignore});
Amit

그것은 나를 위해 일했지만 마지막에 대한 오류를 보여 주었 으로 사용 JsonSerializerSettings하지 않아야 JsonSerializer했습니다
Yazan

1
중요한 한 가지-구체적인 클래스 (개인, 계정 등)에서만 작동합니다. Dictionary에서이 작업을 시도했을 때 작동하지 않았습니다.
chester89

1
@ chester89와 같은 문제가 있습니다. ExpandoObject를 사용하면 null 값이 무시되지 않습니다. 그것은 버그 인 것 같습니다 (json.net 9.0.1 사용)
kwrl

2
답변이 작성되었을 때 JSON.Net은 동적 객체도 지원하지 않았습니다. :) 현재 맞춤 변환기를 사용하여 입찰을 수행 할 수 있습니다.
Mr.

922

JsonProperty속성을 사용하는 대체 솔루션 :

[JsonProperty(NullValueHandling=NullValueHandling.Ignore)]
// or
[JsonProperty("property_name", NullValueHandling=NullValueHandling.Ignore)]

// or for all properties in a class
[JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)]

이 온라인 문서 에서 볼 수 있듯이 .


19
Json.net 속성으로 클래스를 오염시키지 않기 때문에 허용되는 답변이 더 좋습니다.
Sergey

117
@Sergey 사용 사례에 따라 다릅니다. 질문에 언급 된 것처럼 특정 속성에만 사용하려는 경우 이것이 정답입니다. 글로벌 답변을 원하는 경우 JsonSerializer에서 속성을 설정해야합니다.
sibbl

합의-이것은 간단하고 우아합니다. 공감할 가치가 있습니다. 훌륭하게 작동합니다-직렬화하려는 객체의 속성을 VB의 Nothing으로 설정하면 더 이상 JSON의 일부가 아닙니다. 이것은 Strings에서만 작동합니다. 열거 형 또는 정수인 속성은 항상 표시됩니다. Nothing으로 설정하면 기본값이 "0"이됩니다.
Destek

3
@Destek 당신은 참조 타입 필드를 nullable로 만들면 속성이나 설정을 사용하여 직렬화되지 않습니다.
Tony

1
속성이 많은 클래스를 '오염'시키지 않으려면에 처리 규칙을 할당 할 수도 [JsonObject]있지만 속성 이름이 다릅니다. [편집 된 답변]
Simon_Weaver

60

@의 sirthomas의 대답과 마찬가지로, JSON.NET도 존중 특성 에를 :EmitDefaultValueDataMemberAttribute

[DataMember(Name="property_name", EmitDefaultValue=false)]

이것은 당신이 이미 사용하는 경우 바람직 할 수 [DataContract][DataMember]모델 유형과 JSON.NET 특정 속성을 추가 할 수 없습니다.


1
너무 도움이됩니다! 커스텀 Exception 클래스를 디자인하고 거기에 Json.net을 추가하고 싶지 않았습니다. 감사!
jpgrassi

2
이것은 .Net Core에서 작동하지 않았습니다. @sirthomas 답장 추천 : use [JsonProperty (NullValueHandling = NullValueHandling.Ignore)]
Derrick

1
Newtonsoft.Json 10.0.2의 .Net Core에서 나에게 잘 작동합니다.
Karl-Johan Sjögren

33

당신은 쓸 수 있습니다: [JsonProperty("property_name",DefaultValueHandling = DefaultValueHandling.Ignore)]

또한 속성을 기본값 (Null뿐만 아니라)으로 직렬화하지 않도록 처리합니다. 예를 들어 열거 형에 유용 할 수 있습니다.


3
이것은 sirthomas의 답변과 정확히 동일합니다. 왜 추가 했습니까?
OMGtechy

4
네 종류의 정보 DefaultValueHandling 및 NullValueHandling 사이의 차이는 ...이
Vatsal 파텔

4
그러면 대답에서 설명해 주시겠습니까? 언뜻보기에 똑같아 보였으므로 이제는 이것이 다른 답변과 어떻게 다른지 / 칭찬하는 방법을 언급하지 않았다고 언급했습니다.
OMGtechy

1
허용되는 답변은 일부 상황에서 유용 할 수 있지만 항상 사용 가능한 것은 아닙니다. 이것은 의사가 지시 한 것입니다.
Melbourne 개발자

1
나는 이것이 내가 원하는 것이라고 생각합니다. 모든 것이 아니라 특정 속성에 대한 특정 처리.
frostymarvelous

23

직렬화하는 객체의 모든 null을 무시하기 위해이 작업을 수행 할 수 있으며 null 속성은 JSON에 나타나지 않습니다.

JsonSerializerSettings settings = new JsonSerializerSettings();
settings.NullValueHandling = NullValueHandling.Ignore;
var myJson = JsonConvert.SerializeObject(myObject, settings);

12

그들의 사이트 에이 링크에서 볼 수 있듯이 (http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size.aspx) I 기본값을 지정하기 위해 [Default ()] 사용 지원

링크에서 가져온

   public class Invoice
{
  public string Company { get; set; }
  public decimal Amount { get; set; }

  // false is default value of bool
  public bool Paid { get; set; }
  // null is default value of nullable
  public DateTime? PaidDate { get; set; }

  // customize default values
  [DefaultValue(30)]
  public int FollowUpDays { get; set; }
  [DefaultValue("")]
  public string FollowUpEmailAddress { get; set; }
}


Invoice invoice = new Invoice
{
  Company = "Acme Ltd.",
  Amount = 50.0m,
  Paid = false,
  FollowUpDays = 30,
  FollowUpEmailAddress = string.Empty,
  PaidDate = null
};

string included = JsonConvert.SerializeObject(invoice,
  Formatting.Indented,
  new JsonSerializerSettings { });

// {
//   "Company": "Acme Ltd.",
//   "Amount": 50.0,
//   "Paid": false,
//   "PaidDate": null,
//   "FollowUpDays": 30,
//   "FollowUpEmailAddress": ""
// }

string ignored = JsonConvert.SerializeObject(invoice,
  Formatting.Indented,
  new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Ignore });

// {
//   "Company": "Acme Ltd.",
//   "Amount": 50.0
// }


3

.Net Core에서는 이제 훨씬 쉽습니다. startup.cs에서 json 옵션을 추가하면 해당 설정을 구성 할 수 있습니다.


public void ConfigureServices(IServiceCollection services)

....

services.AddMvc().AddJsonOptions(options =>
{
   options.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;               
});

1

Json.NET으로

 public class Movie
 {
            public string Name { get; set; }
            public string Description { get; set; }
            public string Classification { get; set; }
            public string Studio { get; set; }
            public DateTime? ReleaseDate { get; set; }
            public List<string> ReleaseCountries { get; set; }
 }

 Movie movie = new Movie();
 movie.Name = "Bad Boys III";
 movie.Description = "It's no Bad Boys";

 string ignored = JsonConvert.SerializeObject(movie,
            Formatting.Indented,
            new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });

결과는 다음과 같습니다.

{
   "Name": "Bad Boys III",
   "Description": "It's no Bad Boys"
 }

1

System.Text.Json.NET Core 3.0을 사용하면 다음 과 같이 작동했습니다.

var jsonSerializerOptions = new JsonSerializerOptions()
{
    IgnoreNullValues = true
};
var myJson = JsonSerializer.Serialize(myObject, jsonSerializerOptions );

0

GlennG의 매우 유용한 답변에 대해 간단히 설명하기 위해 (구문을 C #에서 VB.Net으로 변환하는 것이 항상 "분명하지는 않습니다") 개별 클래스 속성을 장식하여 null 값 처리 방법을 관리 할 수도 있습니다. 이 작업을 수행하는 경우 GlennG의 제안에서 글로벌 JsonSerializerSettings를 사용하지 않으면 개별 장식이 재정의됩니다. JSON에 null 항목을 표시하여 소비자가 특별한 처리를하지 않아도되는 경우에 유용합니다. 예를 들어 소비자가 옵션 품목의 배열이 일반적으로 사용 가능하지만 현재 비어 있음을 알아야하는 경우 속성 선언의 장식은 다음과 같습니다.

<JsonPropertyAttribute("MyProperty", DefaultValueHandling:=NullValueHandling.Include)> Public Property MyProperty As New List(of String)

해당 속성의 경우 JSON 변경 : = NullValueHandling.Include to : = NullValueHandling.Ignore 에 전혀 표시하고 싶지 않습니다 . 그건 그렇고-XML과 JSON 직렬화에 대한 속성을 잘 꾸밀 수 있습니다 (서로 바로 옆에 두십시오). 이것은 닷넷으로 XML 시리얼 라이저를 호출하거나 NewtonSoft 시리얼 라이저를 자유롭게 호출 할 수있는 옵션을 제공합니다. 둘 다 필요한 고객이 있기 때문에 손잡이에 코딱지가 붙어 있습니다!


0

비슷한 옵션이지만 다른 선택을 제공합니다.

public class DefaultJsonSerializer : JsonSerializerSettings
{
    public DefaultJsonSerializer()
    {
        NullValueHandling = NullValueHandling.Ignore;
    }
}

그런 다음 다음과 같이 사용합니다.

JsonConvert.SerializeObject(postObj, new DefaultJsonSerializer());

차이점은 다음과 같습니다.

  • 인스턴스화 및 구성을 통해 반복되는 코드 감소 JsonSerializerSettings사용되는 각 장소 입니다.
  • 직렬화 할 모든 개체의 모든 속성을 구성하는 시간을 절약합니다.
  • 재사용 가능한 객체에 속성을 명시 적으로 지정하지 않고 다른 개발자에게 직렬화 옵션에 유연성을 제공합니다.
  • 필자의 유스 케이스는 코드가 타사 라이브러리이며 클래스를 재사용하려는 개발자에게 직렬화 옵션을 강요하고 싶지 않다는 것입니다.
  • 잠재적 단점은 다른 개발자가 알아야 할 또 다른 객체이거나 응용 프로그램이 작고이 방법이 단일 직렬화에 중요하지 않다는 것입니다.

-1
var settings = new JsonSerializerSettings();
settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
settings.NullValueHandling = NullValueHandling.Ignore;
//you can add multiple settings and then use it
var bodyAsJson = JsonConvert.SerializeObject(body, Formatting.Indented, settings);

settings.NullValueHandling = NullValueHandling. 다른 답변에서 무시됩니다. 확실하지 않습니다, 귀하의 답변에 새로운 내용
Michael Freidgeim
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.