Skip to content

Instantly share code, notes, and snippets.

@Ningensei848
Last active November 27, 2021 09:52
Show Gist options
  • Save Ningensei848/7c5806189f5734932c45bf201830beae to your computer and use it in GitHub Desktop.
Save Ningensei848/7c5806189f5734932c45bf201830beae to your computer and use it in GitHub Desktop.
Type-safe Validator for SPARQL 1.1 Query Results JSON Format

Type-safe Validator for SPARQL

※日本語での解説記事はこちら

dependency (for TypeScript user)

Usage

import { JSONResponseIsValid } from './validator'

const endpoint = 'https://dbpedia.org/sparql'
const query = `
SELECT * WHERE {
  ?sub ?pred ?obj .
} LIMIT 10
`
const url = `${endpoint}?query=${encodeURIComponent(query)}`

fetch(url)
  .then(response => {
    const data = response.json()
    if (!JSONResponseIsValid(data)) {
      throw new Error('Invalid SPARQL JSON Response.')
    } else {
      return data
    }
  })
  .catch((error) => {
    console.error('Error:', error);
  })

or Demo Application on StackBlitz

for other Languages

If you are using a language such as Python, Ruby, Java, Golang, C# or even Rust, you can refer to the following implementations.

By reusing the predefined schemas below, type-safe implementations can be expected in each language.

reference

SPARQL 1.1 Query Result JSON Format

/*
* We would like to import the schema directly from a JSON file, but that feature is not yet implemented.
* cf. https://github.com/microsoft/TypeScript/issues/32063
*/
const RDFTerm = {
discriminator: 'type',
mapping: {
uri: {
properties: {
value: { type: 'string' },
},
},
literal: {
properties: {
value: { type: 'string' },
},
optionalProperties: {
'xml:lang': { type: 'string' },
datatype: { type: 'string' },
},
},
bnode: {
properties: {
value: { type: 'string' },
},
},
},
} as const
const Results = {
properties: {
bindings: {
elements: {
values: RDFTerm,
},
},
},
additionalProperties: true,
} as const
const Head = {
optionalProperties: {
vars: { elements: { type: 'string' } },
link: { elements: { type: 'string' } },
},
additionalProperties: true,
} as const
export const JSONResponseSchema = {
properties: {
head: Head,
},
optionalProperties: {
results: Results,
boolean: { type: 'boolean' },
},
} as const
{
"properties": {
"head": {
"additionalProperties": true,
"optionalProperties": {
"vars": { "elements": { "type": "string" } },
"link": { "elements": { "type": "string" } }
}
}
},
"optionalProperties": {
"boolean": { "type": "boolean" },
"results": {
"additionalProperties": true,
"properties": {
"bindings": {
"elements": {
"values": {
"discriminator": "type",
"mapping": {
"uri": {
"properties": {
"value": { "type": "string" }
}
},
"literal": {
"properties": {
"value": { "type": "string" }
},
"optionalProperties": {
"xml:lang": { "type": "string" },
"datatype": { "type": "string" }
}
},
"bnode": {
"properties": {
"value": { "type": "string" }
}
}
}
}
}
}
}
}
}
}
import Ajv from 'ajv/dist/jtd'
import type { JTDDataType } from 'ajv/dist/jtd'
import { JSONResponseSchema } from './schema'
type JSONResponse = JTDDataType<typeof JSONResponseSchema>
const ajv = new Ajv()
/*
** validate is a type guard for JSONResponse - type is inferred from JSONResponseSchema type
*/
export const JSONResponseIsValid = ajv.compile<JSONResponse>(JSONResponseSchema)
/*
** serialize will only accept data compatible with JSONResponse
*/
export const JSONResponseSerialize = ajv.compileSerializer<JSONResponse>(JSONResponseSchema)
/*
** parse will return JSONResponse or undefined
*/
export const JSONResponseParse = ajv.compileParser<JSONResponse>(JSONResponseSchema)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment