2017-12-22 11 views
1

Ich möchte ein C# -Objekt als JSON in einen Stream serialisieren, aber die Serialisierung vermeiden, wenn das Objekt nicht gemäß einem Schema gültig ist. Wie soll ich mit dieser Aufgabe mit JSON.NET und Json.NET Schema fortfahren? Von dem, was ich sehe, gibt es keine Methode in der JSON.NET-Bibliothek, die die Validierung eines C# -Objekts gegen ein JSON-Schema erlaubt. Es scheint etwas komisch, dass es keine direkte Methode gibt, das C# -Objekt nur zu validieren, ohne es zu codieren. Haben Sie eine Idee, warum diese Methode nicht verfügbar ist?Validiere Objekt gegen ein Schema vor der Serialisierung

+0

Haben Sie sich das mal angesehen? https://www.newtonsoft.com/json/help/html/JsonSchema.htm –

+1

Sie könnten 'NullJsonWriter' von [Verweis auf automatisch erstellte Objekte] (https://Stackoverflow.com/a/30650904/3744182) dann greifen Wickeln Sie es in einen 'JSchemaValidatingWriter' und testen Sie Ihr Objekt wie in [* JSON mit JSchemaValidatingWriter *] anzeigen (https://www.newtonsoft.com/jsonschema/help/html/JsonValidatingWriterAndSerializer.htm). – dbc

+0

@dbc Es scheint etwas komisch, dass es keine direkte Methode gibt, das C# -Objekt nur zu validieren, ohne es zu codieren. Haben Sie eine Idee, warum diese Methode nicht verfügbar ist? –

Antwort

3

Es scheint, diese API derzeit nicht verfügbar. Bei einer Schätzung könnte dies daran liegen, dass das rekursive Erzeugen der zu validierenden JSON-Werte die meiste Arbeit des Serialisierens des Objekts beinhaltet. Oder es könnte nur sein, weil niemand bei Newtonsoft ever designed, specified, implemented, tested, documented and shipped that feature.

Wenn Sie möchten, könnten Sie file an enhancement request diese API anfordern, wahrscheinlich als Teil der SchemaExtensions class.

In der Zwischenzeit, wenn Sie (das Ergebnis wäre sehr groß, da zB) eine POCO ohne eine vollständige Serialisierung davon Generierung von Test-Validierung brauchen Sie NullJsonWriter von Reference to automatically created objects, wickeln Sie es in einem JSchemaValidatingWriter und Test greifen könnten -serialisieren Sie Ihr Objekt wie in Validate JSON with JSchemaValidatingWriter gezeigt. NullJsonWriter schreibt eigentlich nichts, und damit wird der Leistungs- und Speicheraufwand für das Generieren einer vollständigen Serialisierung eliminiert (entweder als string oder als JToken).

Fügen Sie zunächst die folgende statische Methode:

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. 
    } 
} 

es dann wie verwenden:

// 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 

von der Art und Weise für die Fälle Watch out. Das Json.NET-Schema lautet case sensitive, daher müssen Sie beim Testen der Validierung einen entsprechenden Vertragsresolver verwenden.

Probe fiddle.

0

Sie können nicht tun, aus dem JSON-String, müssen Sie ein Objekt und ein Schema mit dem ersten zu vergleichen ..

public void Validate() 
{ 
    //... 
    JsonSchema schema = JsonSchema.Parse("{'pattern':'lol'}"); 
    JToken stringToken = JToken.FromObject("pie"); 
    stringToken.Validate(schema); 
Verwandte Themen