Open basretera opened 1 month ago
Dit issue ligt alweer 7 dagen zonder enige reactie. Dit moet echt prioriteit krijgen. We lopen in onze testen hier zwaar tegenaan. Hier moet echt snel duidelijkheid over komen!
Ik begrijp het issue niet goed. Kun je een concreet voorbeeld geven waar precies de problemen optreden?
In de specificatie van deze optionele stringvelden staat veelal bovenstaande (voorbeeld) gespecificeerd. Namelijk dat een veld een stringwaarde moet bevatten <= x karakters. Wat wordt hiermee bedoeld? Moeten deze optionele velden dan met een lege stringwaarde "" aangeboden worden? Logischer zou zijn dat deze een null-waarde zouden kunnen hebben. Null-waardes lijkt me toch een beetje de algehele standaard. Maar op andere plekken (zie hieronder) staat weer gespecificeerd string or null voor een vergelijkbaar veld.
En mag je optionele velden helemaal weglaten? Of moet je ze wel altijd teruggeven/meesturen maar dan inderdaad met een null-waarde of lege string-waarde ""?
Kijk ook zeker naar de lopende discussies in de gerelateerde issues.
Namelijk dat een veld een stringwaarde moet bevatten <= x karakters. Wat wordt hiermee bedoeld?
Bijvoorbeeld <= 80
betekent dat de string niet langer mag zijn dan 80. Dus de string mag wel een lengte 0 hebben, oftewel leeg zijn.
Dat snap ik natuurlijk ook. Maar daar gaat het niet om.
En mag je optionele velden helemaal weglaten? Of moet je ze wel altijd teruggeven/meesturen maar dan inderdaad met een null-waarde of lege string-waarde ""?
In principe mag je zelf bepalen of je lege attributen die niet required zijn wel of niet opneemt in een bericht. In een request bericht laat ik de lege attributen altijd weg als ze niet verplicht zijn, lijkt me logisch want waarom zou ik de moeite doen. Echter, bij een respons-bericht vind ik het wel weer prettig als ook de attributen met een lege waarde worden teruggegeven, want dan zie ik namelijk in één oog opslag welke attributen wel of niet gevuld zijn. De referentie-implementatie doet het ook zo.
Dank voor je antwoord, maar het geeft nog steeds geen antwoord op de meest prangende vraag: moet een leeg veld als lege string "" of als null-waarde in een request meegegeven en in een response teruggegeven worden?
In de meeste gevallen zijn de attributen zo gespecificeerd dat er maar één waarde voor het leeg zijn mogelijk is, dus of null of "" (lege string), maar niet beide. Dus daar speelt dit probleem niet. Helaas zijn er een paar gevallen waarbij dit niet goed is gegaan zoals bij het attribuut "processobjectaard". In dat geval moet de API beide waarden ondersteunen (null en lege string). Het is niet fraai maar het werkt wel.
Bij het toevoegen van nieuwe attributen in toekomstige versies moeten we goed in de gaten houden dat we slechts één leeg-waarde toelaten. De vraag is of we in een volgende major release ook alle oude attributen waar dit probleem speelt willen fixen (lees: beperken tot één leeg-waarde) want dat zal mogelijk tot veel backwards compatibiliteits problemen kunnen leiden.
Laatste vraag: Kun jij mij uitleggen waarom er gekozen is voor een lege string "" waarde i.p.v. null? Wat veel logischer lijkt voor mij. Is dat in REST API standaarden gebruikelijker of wat is de reden?
Ik weet niet wat de exacte beweegredenen waren om te kiezen voor een lege string "" i.p.v. null en ik weet ook niet wat de beweegredenen waren om daar weer soms van af te wijken zoals bij het attribuut 'processobjectaard'. Dat was voor mijn tijd. Het niet consequent zijn is een groter probleem dan de waarom-vraag denk ik.
Persoonlijk vind ik het mooier als attributen van het type "string" een lege string "" als lege waarde teruggeven en niet null. Het is namelijk een lege waarde die het datatype string al van zichzelf heeft en je hoeft dan geen nieuw concept zoals null te introduceren. Hetzelfde verhaal voor attributen van het type "array": die geeft je de lege lijst [] terug en niet de waarde null. Immers het datatype array heeft intrinsiek een eigen lege waarde namelijk de lege lijst [] net zoals string ook zijn eigen lege waarde heeft namelijk de lege string "". Het mooie is dan ook dat je in de respons-berichten kunt zien van welke type het lege attribuut is ("" -> string, [] -> array). Dit vind ik fijner dan dat er null had gestaan.
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"url": "https://zaken-api.vng.cloud/api/v1/zaken/01a50969-359c-4a0e-95ca-79293914534b",
"uuid": "01a50969-359c-4a0e-95ca-79293914534b",
"identificatie": "ZAAK-2019-0000000002",
"bronorganisatie": "000000000",
"omschrijving": "aangepast",
"toelichting": "string",
"zaaktype": "https://catalogi-api.vng.cloud/api/v1/zaaktypen/f0cdd277-c62d-4464-a0a7-ddffd6d29f6b",
"registratiedatum": "2019-04-09",
"verantwoordelijkeOrganisatie": "000000000",
"startdatum": "2019-04-09",
"einddatum": null,
"einddatumGepland": "2019-04-20",
"uiterlijkeEinddatumAfdoening": "2019-04-09",
"publicatiedatum": "2019-04-09",
"communicatiekanaal": "",
"productenOfDiensten": [],
"vertrouwelijkheidaanduiding": "openbaar",
"betalingsindicatie": "geheel",
"betalingsindicatieWeergave": "De met de zaak gemoeide kosten zijn geheel betaald.",
"laatsteBetaaldatum": null,
"zaakgeometrie": {
"type": "Point",
"coordinates": [
53.0,
5.0
]
},
"verlenging": {
"reden": "",
"duur": null
},
"opschorting": {
"indicatie": true,
"reden": "string"
},
"selectielijstklasse": "https://referentielijsten-api.vng.cloud/api/v1/resultaten/fb65ae34-e820-4ace-815a-cf5da7d04a12",
"hoofdzaak": null,
"deelzaken": [],
"relevanteAndereZaken": [],
"eigenschappen": [
"https://zaken-api.vng.cloud/api/v1/zaken/01a50969-359c-4a0e-95ca-79293914534b/zaakeigenschappen/e5235521-e735-40a3-8005-2b9953757c2c"
],
"rollen": [],
"status": null,
"zaakinformatieobjecten": [],
"zaakobjecten": [],
"kenmerken": [],
"archiefnominatie": null,
"archiefstatus": "nog_te_archiveren",
"archiefactiedatum": null,
"resultaat": null,
"opdrachtgevendeOrganisatie": "",
"processobjectaard": null,
"startdatumBewaartermijn": null,
"processobject": {
"datumkenmerk": "",
"identificatie": "",
"objecttype": "",
"registratie": ""
}
}
]
}
In mijn ogen is de definitie van het attribuut "processobjectaard" een designfout en had er een lege string "" teruggegeven moeten worden in plaats van null. Want alle andere attributen van het type string geven wel een lege string "" terug zoals datumkenmerk, identificatie, objecttype , etc.
OpenAPI maakt gebruik van JsonSchema (ze zijn niet 100% gelijk, maar bewegen wel die kant op), dus om deze vraag te beantwoorden moet je naar de details van JsonSchema kijken. Een eenvoudig voorbeeld:
type: object
required:
- property1
properties:
property1:
type: string
maxLength: 80
property2:
type:
- string
- 'null'
maxLength: 20
required
betekent dat deze attributen (property1
) altijd aanwezig moeten zijn. {}
is dus niet valide, {"property1": ""}
en {"property1": "", "property2": ""}
zijn dat wel. Required zegt nooit iets of een lege waarde toegestaan is of niet, alleen of er een garantie is dat de key aanwezig is of niet.property1
heeft als mogelijke datatypes (meervoud belangrijk!) enkel string
, met hierboven een extra restrictie: maximaal 80 karakters. Dus, deze mag een lege string zijn, maar mag niet afwezig zijn en mag niet langer dan 80 karakters zijn.property2
heeft als mogelijke datatypes string
en null
. Dus, als de property aanwezig is, dan mag die null
zijn, en als die een string
is, dan mag die een lege string zijn of maximaal 20 karakters tellen. De property mag ook helemaal afwezig zijn.Extra validates zijn altijd bovenop het type waarop de validatie betrekking heeft. maxLength
heeft geen betekenis voor null
, en is dus niet relevant. Een property die niet required is, mag enkel als null
meegestuurd worden als het type van de property null
toestaat.
In OpenAPI 3.1 gebruiken ze deze array voor types, voor eerdere versie is hier de nullable: true
schema key beschikbaar (even uit het hoofd).
De volgende ("lege") data objecten zijn dus wel geldig voor het schema hierboven:
{"property1": ""}
{"property1": "", "property2": ""}
{"property1": "", "property2": null}
Dit is een onderwerp waar veel verwarring over bestaat, maar het is wel gespecifieerd in de onderliggende JsonSchema specificatie.
@HenriKorver
Persoonlijk vind ik het mooier als attributen van het type "string" een lege string "" als lege waarde teruggeven en niet null. Het is namelijk een lege waarde die het datatype string al van zichzelf heeft en je hoeft dan geen nieuw concept zoals null te introduceren. Hetzelfde verhaal voor attributen van het type "array": die geeft je de lege lijst [] terug en niet de waarde null. Immers het datatype array heeft intrinsiek een eigen lege waarde namelijk de lege lijst [] net zoals string ook zijn eigen lege waarde heeft namelijk de lege string "".
Hier zit wel nuance die relevant kan zijn! null
is een weergave dat er niets gezet is, het is onbekende informatie. Terwijl een lege array []
gewoon kan betekenen dat er wel iets gezet is, maar er is geen relevante informatie. null
lees je typisch als "onbepaald", in plaats van "leeg". Tri-state logica kent bijvoorbeeld true | false | null
om dit weer te geven.
@sergei-maertens Dank voor je heldere uiteenzetting!
Bovenstaande maakt het een en ander duidelijk maar ik heb nog een vervolg vraag. Is "" een geldige waarde voor een url/datum/duration? Voor enum kan ik afleiden dat dit niet het geval is omdat er soms expliciet een "Empty Enum" optie staat gespecifieerd.
Voor de zekerheid heb ik het zelf even getoetst op https://www.jsonschemavalidator.net/, met schema:
{
"type": "string",
"format": "date-time"
}
en waarde:
""
en deze is inderdaad niet geldig. Daarom zou je dus typisch wel null
toelaten om een onbekende waarde te communiceren.
Alledrie de voorbeelden die je noemt zijn ongeldig met lege-string.
In onze testen met andere leveranciers lopen we tegen een issue aan m.b.t. optionele string velden. Via dit issue wil ik nogmaals vragen om een uitspraak te doen in hoe we hiermee om moeten gaan aangezien de standaard niet eenduidig is. Dit issue is in navolging op issue #1901 en issue #2090 aan. De standaard is gewoonweg niet duidelijk genoeg hierin. Wat moeten we nu doen met niet verplichte (string) velden? Opties die er zijn:
Optie 3 vind ik totaal niet fraai, maar het belangrijkste is dat er duidelijkheid komt. De voorgaande issues staan inmiddels 1,5 jaar open en iedere leverancier maakt hier zijn eigen keuzes in die mogelijkerwijs niet stroken met elkaar. Graag op korte termijn een uitspraak hierover zodat het voor alle leveranciers duidelijk is.