xeipuuv / gojsonschema

An implementation of JSON Schema, draft v4 v6 & v7 - Go language
2.51k stars 357 forks source link

gojsonschema does not handle duplicate fields #78

Open Bienne opened 8 years ago

Bienne commented 8 years ago

Hello. gojsonschema does not handle duplicate fields and only keeps the last occurence. Can you throw an error when processing duplicate fields? Thank you.

Here is a sample ("firstName" field occurs twice ( "Petr" and "Ivan") ):

package main

import ( "fmt" "github.com/xeipuuv/gojsonschema" )

func main() { src := { "firstName" : "Petr", "firstName" : "Ivan", "lastName" : "Petrov" }

schema := `{
    "title": "test",
    "type": "object",
    "properties": {
        "firstName": {
            "type": "string"
        },
        "lastName": {
            "type": "string"
        }
    },
    "required": ["firstName", "lastName"],
    "additionalProperties": false
}`

documentLoader := gojsonschema.NewStringLoader(src)
schemaLoader := gojsonschema.NewStringLoader(schema)
result, err := gojsonschema.Validate(schemaLoader, documentLoader)
if err != nil {
    panic(err.Error())
}

if result.Valid() {
    fmt.Printf("The document is valid\n")
} else {
    fmt.Printf("Errors :\n")
    for _, desc := range result.Errors() {
        fmt.Printf("- %s\n", desc)
    }
}

}

cristiangraz commented 8 years ago

I'm not sure this is really a bug with this library. If you run this:

package main

import(
    "encoding/json"
    "log"
    "strings"
)

func main() {
    var document interface{}

    decoder := json.NewDecoder(strings.NewReader(`{ "firstName" : "Petr", "firstName" : "Ivan", "lastName" : "Petrov" }`))
    decoder.UseNumber()

    err := decoder.Decode(&document)
    if err != nil {
        log.Println(err)    
        return
    }

    log.Println(document)
}

The output is map[firstName:Ivan lastName:Petrov]

The Go standard library doesn't retain duplicate properties. I'm not really sure what could be done here to detect this.

handrews commented 7 years ago

According to RFC 7159, Section 4:

When the names within an object are not unique, the behavior of software that receives such an object is unpredictable. Many implementations report the last name/value pair only. Other implementations report an error or fail to parse the object, and some implementations report all of the name/value pairs, including duplicates.

So the Go standard library technically conforms to the JSON specification with its current behavior. You would have to separately parse out the property names and check for duplicates in order to catch the error.

stevenroose commented 7 years ago

IIRC it is valid in JSON to have duplicate keys and only the last one is considered when interpreting the document.

F.e. https://stackoverflow.com/questions/244777/can-comments-be-used-in-json/18018493#18018493

handrews commented 7 years ago

@stevenroose valid, yes. Dependable? Interoperable? No. Which is what that big "WARNING" at the top of that linked stackoverflow thread is about. You can only use that if you have absolute control over what implementations consume your JSON, including the version of the implementation. A conforming JSON parser could change behavior in this scenario and still remain in conformance both before and after.