95 lines
2.9 KiB
Go
95 lines
2.9 KiB
Go
//go:build goexperiment.jsonv2
|
|
|
|
package doc
|
|
|
|
import (
|
|
"encoding/json"
|
|
)
|
|
|
|
// ValidateJsonMLBodyV2 validates a JSONML body using schema-v2.
|
|
// This implementation delegates to the new Parse → ValidateWithSchema pipeline,
|
|
// providing position-aware diagnostics. The signature is unchanged for backward
|
|
// compatibility (SPEC §8.4).
|
|
//
|
|
// Note: Since input is already []any, we marshal it back to JSON bytes to feed
|
|
// the parser. Positions are relative to the marshaled output. The full pipeline
|
|
// (parsing raw input directly) provides original-source positions.
|
|
//
|
|
// Behavioral note: The old implementation interprets a body whose first element
|
|
// is an unknown tag (not "root", not a known schema tag) as an "array of blocks"
|
|
// and would error on each non-array element. The new Parse-based implementation
|
|
// correctly interprets ["unknownTag", ...] as a single JSONML element with an
|
|
// unknown tag (warning). This is semantically more correct for JSONML.
|
|
func ValidateJsonMLBodyV2(body []any) *JsonMLValidationResult {
|
|
if len(body) == 0 {
|
|
return &JsonMLValidationResult{}
|
|
}
|
|
|
|
// Marshal body back to JSON bytes for the parser
|
|
src, err := json.Marshal(body)
|
|
if err != nil {
|
|
r := &JsonMLValidationResult{}
|
|
r.Errors = append(r.Errors, "internal: failed to marshal body for validation: "+err.Error())
|
|
return r
|
|
}
|
|
|
|
// Layer 0 + Layer 1: Parse
|
|
doc := Parse(src)
|
|
|
|
// Layer 2: Schema validation
|
|
schemaDiags := ValidateWithSchema(doc, schemaV2)
|
|
|
|
// Merge all diagnostics
|
|
allDiags := append(doc.Diagnostics, schemaDiags...)
|
|
|
|
return allDiags.ToLegacyResult()
|
|
}
|
|
|
|
// ValidateJsonMLNodeV2 validates a single JSONML node using schema-v2.
|
|
// Delegates to the new Parse → ValidateWithSchema pipeline.
|
|
func ValidateJsonMLNodeV2(node any) *JsonMLValidationResult {
|
|
// Marshal single node to JSON bytes
|
|
src, err := json.Marshal(node)
|
|
if err != nil {
|
|
r := &JsonMLValidationResult{}
|
|
r.Errors = append(r.Errors, "internal: failed to marshal node for validation: "+err.Error())
|
|
return r
|
|
}
|
|
|
|
// Layer 0 + Layer 1: Parse
|
|
doc := Parse(src)
|
|
|
|
// Layer 2: Schema validation
|
|
schemaDiags := ValidateWithSchema(doc, schemaV2)
|
|
|
|
// Merge all diagnostics
|
|
allDiags := append(doc.Diagnostics, schemaDiags...)
|
|
|
|
return allDiags.ToLegacyResult()
|
|
}
|
|
|
|
// ValidateJsonMLSource validates raw JSONML source bytes directly,
|
|
// preserving original line/column positions in diagnostics.
|
|
// This should be preferred over ValidateJsonMLBodyV2 when the original
|
|
// source bytes are available (e.g., from a file).
|
|
//
|
|
// The input can be:
|
|
// - A bare JSONML array: ["root", {}, ...]
|
|
// - A wrapped object: {"jsonml": [...]}
|
|
func ValidateJsonMLSource(src []byte) *JsonMLValidationResult {
|
|
if len(src) == 0 {
|
|
return &JsonMLValidationResult{}
|
|
}
|
|
|
|
// Layer 0 + Layer 1: Parse
|
|
doc := Parse(src)
|
|
|
|
// Layer 2: Schema validation
|
|
schemaDiags := ValidateWithSchema(doc, schemaV2)
|
|
|
|
// Merge all diagnostics
|
|
allDiags := append(doc.Diagnostics, schemaDiags...)
|
|
|
|
return allDiags.ToLegacyResult()
|
|
}
|