2017-12-22 4 views
1

C# 개체를 JSON 형식으로 직렬화하려고하지만 개체가 스키마에 따라 유효하지 않은 경우 직렬화를 피하려고합니다. JSON.NET 및 Json.NET 스키마를 사용하여이 작업을 어떻게 진행해야합니까? 내가 본 것으로부터 JSON 스키마에 대한 C# 개체의 유효성 검사를 허용하는 JSON.NET 라이브러리에는 메서드가 없습니다. C# 개체를 인코딩하지 않고 유효성을 검사하는 직접적인 메서드가 없다는 것은 이상한 것처럼 보입니다. 이 방법을 사용할 수없는 이유를 알고 있습니까?직렬화 전에 스키마에 대해 개체 유효성 검사

+0

이 사진을 보셨습니까? https://www.newtonsoft.com/json/help/html/JsonSchema.htm –

+1

[자동 생성 된 개체 참조] (https://stackoverflow.com/a/30650904/3744182)에서'NullJsonWriter'를 가져올 수 있습니다. 'JSchemaValidatingWriter'에 랩핑하고 [* JSchemaValidatingWriter *로 JSON 확인] (https://www.newtonsoft.com/jsonschema/help/html/JsonValidatingWriterAndSerializer.htm)과 같이 객체를 테스트 직렬화하십시오. – dbc

+0

@dbc 그것은 C# 개체를 인코딩하지 않고 유효성을 검사하는 직접적인 메서드가 없다는 다소 이상한 것처럼 보입니다. 이 방법을 사용할 수없는 이유를 알고 있습니까? –

답변

3

그것은이 API는 현재 사용할 수없는 것 같다. JSON 값을 재귀 적으로 생성하여 유효성을 검사하기 때문에 대부분의 객체 직렬화 작업이 필요하기 때문일 수 있습니다. 아니면 Newtonsoft에 아무도 없기 때문일 수도 있습니다. ever designed, specified, implemented, tested, documented and shipped that feature.

원하는 경우 file an enhancement requestSchemaExtensions class의 일부로이 API를 요청할 수 있습니다. 한편

, 당신은 (예를 들어 있기 때문에 결과가 매우 큰 것), 당신은 Reference to automatically created objects에서 NullJsonWriter을 잡아 JSchemaValidatingWriter 및 테스트에 포장 할 수 그것의 완전한 직렬화를 생성하지 않고 POCO을 테스트-확인해야하는 경우 - Validate JSON with JSchemaValidatingWriter과 같이 개체를 직렬화하십시오. NullJsonWriter은 실제로 아무 것도 쓰지 않으므로 완전한 직렬화 ( string 또는 JToken)를 생성 할 때 발생하는 성능 및 메모리 오버 헤드가 제거됩니다.

먼저 다음 정적 메서드를 추가

public static class JsonExtensions 
{ 
    public static bool TestValidate<T>(T obj, JSchema schema, SchemaValidationEventHandler handler = null, JsonSerializerSettings settings = null) 
    { 
     using (var writer = new NullJsonWriter()) 
     using (var validatingWriter = new JSchemaValidatingWriter(writer) { Schema = schema }) 
     { 
      int count = 0; 
      if (handler != null) 
       validatingWriter.ValidationEventHandler += handler; 
      validatingWriter.ValidationEventHandler += (o, a) => count++; 
      JsonSerializer.CreateDefault(settings).Serialize(validatingWriter, obj); 
      return count == 0; 
     } 
    } 
} 

// Used to enable Json.NET to traverse an object hierarchy without actually writing any data. 
class NullJsonWriter : JsonWriter 
{ 
    public NullJsonWriter() 
     : base() 
    { 
    } 

    public override void Flush() 
    { 
     // Do nothing. 
    } 
} 

그 다음이 좋아 사용

// Example adapted from 
// https://www.newtonsoft.com/jsonschema/help/html/JsonValidatingWriterAndSerializer.htm 
// by James Newton-King 

string schemaJson = @"{ 
    'description': 'A person', 
    'type': 'object', 
    'properties': { 
    'name': {'type':'string'}, 
    'hobbies': { 
     'type': 'array', 
     'maxItems': 3, 
     'items': {'type':'string'} 
    } 
    } 
}";   
var schema = JSchema.Parse(schemaJson); 

var person = new 
{ 
    Name = "James", 
    Hobbies = new [] { ".Net", "Blogging", "Reading", "XBox", "LOLCATS" }, 
}; 

var settings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }; 
var isValid = JsonExtensions.TestValidate(person, schema, (o, a) => Console.WriteLine(a.Message), settings); 
// Prints Array item count 5 exceeds maximum count of 3. Path 'hobbies'. 

Console.WriteLine("isValid = {0}", isValid); 
// Prints isValid = False 

이 그런데 경우에 조심. Json.NET 스키마는 case sensitive이므로 테스트 유효성 검사를 할 때 적절한 계약 리졸버를 사용해야합니다.

샘플 fiddle.

0

당신은 JSON 문자열에서, 당신은 객체와 처음으로 비교하는 스키마를 필요로 할 수 없다 ..

public void Validate() 
{ 
    //... 
    JsonSchema schema = JsonSchema.Parse("{'pattern':'lol'}"); 
    JToken stringToken = JToken.FromObject("pie"); 
    stringToken.Validate(schema); 
관련 문제