2017-07-24 4 views
1

Verwendung von Python und jsonschema Ich versuche, die Zuordnung von ObjA oder ObjB usw. zu beta (test.json)Wie spezifiziert man, welches oneOf Item ein JSON Objekt nehmen soll?

{ 
    "alpha": { 

     "beta": "ObjA" 
    } 
} 

In meinem Schema (testschema.json) beta ist oneOf eine Anzahl von Elementen und jedes Element definiert ist, zu validieren unten (mit Werten für a, b und c unterschiedlichen)

"ObjA": { 

    "type": "object", 
    "properties": { 

     "items": { 

      "a": [90, 95], 
      "b": [4, 8], 
      "c": [0.2, 0.6] 
     } 
    }, 

    "additionalProperties": false 
} 

Das heißt, beta kann oneOf Werte annehmen, die ObjA, ObjB, ObjC und ObjD sind. Ich versuche einfach angeben, welche man es jedoch in test.json

"alpha": { 

    "type": "object", 
    "properties": { 

     "beta": { 

      "oneOf": [ 
       { 
        "type": "object", 
        "properties": { 

         "ObjA": { 

          "type": "object", 
          "properties": { 

           "items": { 

            "a": [90, 95], 
            "b": [4, 8], 
            "c": [0.2, 0.6] 
           } 
          }, 

          "additionalProperties": false 
         } 
        }, 

        "additionalProperties": false 
       }, 

       { 
        "type": "object", 
        "properties": { 

         "ObjB": { 

          "type": "object", 
          "properties": { 

           "items": { 

            "a": [100], 
            "b": [0], 
            "c": [0] 
           } 
          }, 

          "additionalProperties": false 
         } 
        } 
       }, 

       ... 
       ObjC and ObjD defined 
       ... 
      } 
     } 
    } 
}, 

verwenden sollten, wenn sie gegen das Schema zu validieren versucht, mit jsonschema.validate()

### Test the whole JSON is valid against the Schema 
def test_valid__JSON_against_schema(self): 

    with open(schema_filename) as schema_file: 
     test_schema = json.load('testschema.json') 
    schema_file.close() 

    with open(json_filename) as json_file: 
     test_json = json.load('test.json') 
    json_file.close() 

    validate(test_json, test_schema) 

ich folgende Fehlermeldung

Failed validating 'oneOf' in schema['properties']['alpha']['properties']['beta']: 
bekommen

Hier ist die ganze Nachricht

E                  
====================================================================== 
ERROR: test_valid__JSON_against_schema (__main__.SchemaTests)   
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "test_test-variables.py", line 35, in test_valid__JSON_against_schema 
    validate(test_json, test_schema) 
    File "/local/tools/PACKAGES/python3/lib/python3.6/site-packages/jsonschema/validators.py", line 541, in validate 
    cls(schema, *args, **kwargs).validate(instance) 
    File "/local/tools/PACKAGES/python3/lib/python3.6/site-packages/jsonschema/validators.py", line 130, in validate 
    raise error 
jsonschema.exceptions.ValidationError: 'ObJA' is not valid under any of the given schemas 

Failed validating 'oneOf' in schema['properties']['alpha']['properties']['beta']: 
    {'oneOf': [{'additionalProperties': False, 
       'properties': {'ObjA': {'additionalProperties': False, 
              'properties': {'items': {'a': [0.2, 0.6], 
                    'b': [90, 95], 
                    'c': [4, 8]}}, 
              'type': 'object'}}, 
       'type': 'object'}, 
       {'additionalProperties': False, 
       'properties': {'ObjB': {'additionalProperties': False, 
              'properties': {'items': {'a': [0], 
                    'b': [100], 
                    'c': [0]}}, 
              'type': 'object'}}, 
       'type': 'object'}, 
       {'additionalProperties': False, 
       'properties': {'ObjC': {'additionalProperties': False, 
                'properties': {'items': {'a': [0], 
                      'b': [50], 
                      'c': [50]}}, 
                'type': 'object'}}, 
       'type': 'object'}, 
       {'additionalProperties': False, 
       'properties': {'ObjD': {'additionalProperties': False, 
               'properties': {'items': {'a': [100], 
                     'b': [0], 
                     'c': [0]}}, 
               'type': 'object'}}, 
       'type': 'object'}]} 

On instance['alpha']['beta']: 
    'ObjA' 

---------------------------------------------------------------------- 
Ran 1 test in 0.007s 

FAILED (errors=1) 

Mit dem online jsonschema Validator (http://json-schema-validator.herokuapp.com/) test.json wird nicht validiert, so dass ich jede Erwähnung von alpha aus der Datei (d. H. auf diese { }) und dem Validator berichtete die folgende

[ { 
    "level" : "warning", 
    "schema" : { 
    "loadingURI" : "#", 
    "pointer" : "/properties/alpha/properties/beta/oneOf/0/properties/ObjA/properties/items" 
    }, 
    "domain" : "syntax", 
    "message" : "the following keywords are unknown and will be ignored: [a, b, c]", 
    "ignored" : [ "a", "b", "c" ] 
} ] 

test.json Wiederherstellen zurück, gibt die Validierung

[ { 
    "level" : "warning", 
    "schema" : { 
    "loadingURI" : "#", 
    "pointer" : "/properties/alpha/properties/beta/oneOf/0/properties/ObjA/properties/items" 
    }, 
    "domain" : "syntax", 
    "message" : "the following keywords are unknown and will be ignored: [a, b, c]", 
    "ignored" : [ "a", "b", "c" ] 
}, { 
    "level" : "warning", 
    "schema" : { 
    "loadingURI" : "#", 
    "pointer" : "/properties/alpha/properties/beta/oneOf/0/properties/ObjA/properties/items" 
    }, 
    "domain" : "syntax", 
    "message" : "the following keywords are unknown and will be ignored: [a, b, c]", 
    "ignored" : [ "a", "b", "c" ] 
}, { 
    "level" : "warning", 
    "schema" : { 
    "loadingURI" : "#", 
    "pointer" : "/properties/alpha/properties/beta/oneOf/0/properties/ObjA/properties/items" 
    }, 
    "domain" : "syntax", 
    "message" : "the following keywords are unknown and will be ignored: [a, b, c]", 
    "ignored" : [ "a", "b", "c" ] 
}, { 
    "level" : "error", 
    "schema" : { 
    "loadingURI" : "#", 
    "pointer" : "/properties/alpha/properties/beta" 
    }, 
    "instance" : { 
    "pointer" : "/alpha/beta" 
    }, 
    "domain" : "validation", 
    "keyword" : "oneOf", 
    "message" : "instance failed to match exactly one schema (matched 0 out of 1)", 
    "matched" : 0, 
    "nrSchemas" : 1, 
    "reports" : { 
    "/properties/alpha/properties/beta/oneOf/0" : [ { 
     "level" : "warning", 
     "schema" : { 
     "loadingURI" : "#", 
     "pointer" : "/properties/alpha/properties/beta/oneOf/0/properties/ObjA/properties/items" 
     }, 
     "domain" : "syntax", 
     "message" : "the following keywords are unknown and will be ignored: [a, b, c]", 
     "ignored" : [ "a", "b", "c" ] 
    }, { 
     "level" : "error", 
     "schema" : { 
     "loadingURI" : "#", 
     "pointer" : "/properties/alpha/properties/beta/oneOf/0" 
     }, 
     "instance" : { 
     "pointer" : "/alpha/beta" 
     }, 
     "domain" : "validation", 
     "keyword" : "type", 
     "message" : "instance type (string) does not match any allowed primitive type (allowed: [\"object\"])", 
     "found" : "string", 
     "expected" : [ "object" ] 
    } ] 
    } 
} ] 

Kennt jemand die richtige Art und Weise, dies zu tun?

Danke.

+0

Fast unmöglich zu helfen, ohne zu wissen, wie die JSON-Instanz aussieht, die Sie zu validieren versuchen. Da Sie es dynamisch generieren, könnte es alles sein. –

+0

Beginn des Textes - "beta": "ObjA" - Ich habe den Satz und JSON so bearbeitet, dass es klarer ist. – Dodomac

+0

Ja, das ist genau das Problem. Sie erhalten einen Validierungsfehler, wenn Sie versuchen, "etwas" gegen ein Schema zu validieren. Das "Etwas", das Sie zu validieren versuchen, ist fehlgeschlagen. Leider ist es für uns unmöglich zu sehen, warum es scheitert (und Ihnen daher helfen zu können), weil wir nicht wissen, wie es aussieht. –

Antwort

3

Lassen Sie uns den Teil des Schemas isolieren, der fehlschlägt.

{ 
    "type": "object", 
    "properties": { 
    "ObjA": { 
     "type": "object", 
     "properties": { 
     "items": { 
      "a": [90, 95], 
      "b": [4, 8], 
      "c": [0.2, 0.6] 
     } 
     }, 
     "additionalProperties": false 
    } 
    }, 
    "additionalProperties": false 
} 

, um diesen Teil von Ihnen ist valiating Testdaten

"ObjA" 

Der Fehler, den Sie sehen, ist Ihnen zu sagen, dass die Testdaten ein String ist, aber das Schema setzt voraus, dass es sich um ein Objekt sein.

Testdaten, die das Schema passt wäre so etwas wie dieses

{ 
    "ObjA": { 
    "items": ??? 
    } 
} 

sehe ich verwenden ??? hier, weil der Wert hier kann ein beliebiger Wert sein, die gültige JSON ist. Der Grund dafür ist, dass dieses Schema keine JSON-Schema-Schlüsselwörter enthält.

{ 
    "a": [90, 95], 
    "b": [4, 8], 
    "c": [0.2, 0.6] 
} 

Daher gibt es keine Einschränkungen auf welchen Wert es sein kann.Die Warnmeldungen, die Sie sehen, sagen Ihnen, dass a, b und c keine Schlüsselwörter sind.

Ich weiß nicht, was Sie mit diesem Schema ausdrücken wollen, aber es ist weit entfernt von der einfachen Zeichenfolge in Ihren Testdaten.

bearbeiten in Reaktion auf die Kommentare

Es klingt wie Sie es für JSON Schema zu verwenden, um etwas versuchen, für nicht ausgelegt. Das Schema sollte nur beschreiben, worüber der Benutzer besorgt sein muss. Sie müssen die Benutzerwerte in einem anderen Schritt der fest codierten Struktur zuordnen. In jedem Fall klingt es wie, was Sie brauchen, ist enum anstatt oneOf.

{ 
    "enum": ["ObjA", "ObjB", "ObjC", "ObjD"] 
} 

oder

{ 
    "enum": [ 
    { 
     "a": [90, 95], 
     "b": [4, 8], 
     "c": [0.2, 0.6] 
    }, 
    { 
     "a": [100], 
     "b": [0], 
     "c": [0] 
    }, 
    ... 
    ] 
} 

Es gibt keine Möglichkeit, beides zu haben. Wenn Sie das in Ihrem Schema wirklich ausdrücken müssen, würde ich ein benutzerdefiniertes Schlüsselwort hinzufügen, das das Mapping anzeigt. Ein Validierer wird es ignorieren (und Sie könnten eine Warnung erhalten), aber die Beziehung wird für menschliche Leser und vielleicht benutzerdefinierte Werkzeuge ausgedrückt. Es könnte so etwas wie dieses

{ 
    "enum": ["ObjA", "ObjB", "ObjC", "ObjD"] 
    "enumValues": { 
    "ObjA": { 
     "a": [90, 95], 
     "b": [4, 8], 
     "c": [0.2, 0.6] 
    }, 
    "ObjB": { 
     "a": [100], 
     "b": [0], 
     "c": [0] 
    }, 
    ... 
    ] 
} 

aussehen

The enum teilt dem Benutzer mit, welche Werte erlaubt sind und der Validator können dies überprüfen. Dann ist das Schlüsselwort enumValues etwas, das wir erfunden haben, um die Beziehung zwischen den Enum-Werten und ihren tatsächlichen Werten auszudrücken.

+0

Die Werte a, b und c sind feste Arrays für ObjA, ObjB, ObjC und ObjD. Ich möchte einfach das ganze ObjA der Beta zuweisen, ohne seinen festen Inhalt zu spezifizieren, oder mit anderen Worten, ich versuche, ein JSON-Objekt mit mehreren Arrays zu belegen, indem ich nur das Objekt zuweise. Ich werde diese Information zur ursprünglichen Frage hinzufügen. – Dodomac

+0

+1 zur Identifizierung des Problems. Brauchen Sie noch eine Möglichkeit, ein Objekt mit mehreren Arrays von festgelegten Werten (a, b und c) korrekt anzugeben. In einem Objekt (ObjA), das ausgewählt werden muss. – Dodomac

+0

Vielleicht ist das Problem, dass ich versuche, Werte im Schema anzugeben (auf die Sie hier verweisen https://Stackoverflow.com/a/30465935/1413785). Der Grund dafür ist, dass ich nicht möchte, dass der Benutzer diese Werte als festgelegte Werte für einen Testtyp angibt, den sie ausführen möchten. – Dodomac

Verwandte Themen