Lors du transfert d'un objet via une API, comme au format JSON sans schéma, quel est le moyen idéal pour renvoyer une propriété de chaîne inexistante? Je sais qu'il existe différentes façons de procéder, comme dans les exemples des liens ci-dessous.
Je suis sûr que j'ai utilisé null dans le passé, mais je n'ai pas de bonnes raisons de le faire. Il semble simple d'utiliser null lorsqu'il s'agit de la base de données. Mais la base de données semble être un détail d'implémentation qui ne devrait pas concerner la partie de l'autre côté de l'API. Par exemple, ils utilisent probablement une banque de données sans schéma qui stocke uniquement les propriétés avec des valeurs (non nulles).
Du point de vue du code, restreindre les fonctions de chaîne pour ne fonctionner qu'avec un seul type, c'est-à-dire string
(non nul), les rend plus faciles à prouver; éviter null est également une raison pour avoir un Option
objet. Donc, si le code qui produit la demande / réponse n'utilise pas null, je suppose que le code de l'autre côté de l'API ne sera pas forcé d'utiliser également null.
J'aime plutôt l'idée d'utiliser une chaîne vide comme moyen facile d'éviter d'utiliser null. Un argument que j'ai entendu pour utiliser null et contre la chaîne vide est que la chaîne vide signifie que la propriété existe. Bien que je comprenne la différence, je me demande également si ce n'est que le détail de l'implémentation et si l'utilisation d'une chaîne nulle ou vide fait une réelle différence. Je me demande également si une chaîne vide est analogue à un tableau vide.
Alors, quelle est la meilleure façon de le faire pour répondre à ces préoccupations? Cela dépend-il du format de l'objet transféré (schéma / sans schéma)?
la source
if( value === null) { use parent value; }
Cependant, si vous définissez la valeur enfant, même sur une chaîne vide (par exemple, remplacez la valeur par défaut par un blanc), alors comment "héritez-vous" de la valeur? Pour moi, le définir sur null signifierait «annuler la définition de cette valeur afin que nous sachions utiliser la valeur parente».null
(c'est vrai quinull
est évité en tant que tel), l'interrogateur signifie "Retourner un objet non nul" (Objet: chaîne vide, tableau vide, etc.) quand ils écrivez «éviter».Réponses:
TLDR; Supprimer les propriétés nulles
La première chose à garder à l'esprit est que les applications à leurs bords ne sont pas orientées objet (ni fonctionnelles si la programmation dans ce paradigme). Le JSON que vous recevez n'est pas un objet et ne doit pas être traité comme tel. Ce sont juste des données structurées qui peuvent (ou non) se convertir en objet. En général, aucun JSON entrant ne doit être approuvé en tant qu'objet métier tant qu'il n'est pas validé en tant que tel. Le simple fait qu'il ait désérialisé ne le rend pas valide. Étant donné que JSON a également des primitives limitées par rapport aux langages principaux, il vaut souvent la peine de créer un DTO aligné sur JSON pour les données entrantes. Utilisez ensuite le DTO pour construire un objet métier (ou une erreur lors de la tentative) pour exécuter l'opération d'API.
Lorsque vous regardez JSON comme un simple format de transmission, il est plus logique d'omettre des propriétés qui ne sont pas définies. C'est moins d'envoyer à travers le fil. Si votre langue principale n'utilise pas de valeurs par défaut, vous pouvez probablement configurer votre désérialiseur pour qu'il génère une erreur. Par exemple, ma configuration courante pour Newtonsoft.Json traduit uniquement les propriétés nulles / manquantes en / à partir des
option
types F # et entraînera sinon une erreur. Cela donne une représentation naturelle des champs facultatifs (ceux deoption
type).Comme toujours, les généralisations ne vous mènent que jusqu'à présent. Il y a probablement des cas où une propriété par défaut ou nulle correspond mieux. Mais la clé n'est pas de regarder les structures de données en bordure de votre système comme des objets métier. Les objets métier doivent comporter des garanties commerciales (par exemple, nommer au moins 3 caractères) lorsqu'ils sont créés avec succès. Mais les structures de données retirées du fil n'ont aucune réelle garantie.
la source
Mise à jour: j'ai un peu édité la réponse, car cela peut être source de confusion.
Aller avec une chaîne vide est un non définitif. Une chaîne vide est toujours une valeur, elle est juste vide. Aucune valeur doit être indiquée en utilisant une construction qui ne représente rien,
null
.Du point de vue du développeur d'API, il n'existe que deux types de propriétés:
null
.Cela montre clairement que lorsqu'une propriété est obligatoire, c.-à-d. nécessaire, il ne peut jamais l'être
null
.D'un autre côté, si une propriété facultative d'un objet n'est pas définie et laissée vide, je préfère de toute façon les conserver dans la réponse avec la
null
valeur. D'après mon expérience, il est plus facile pour les clients API d'implémenter l'analyse, car ils ne sont pas tenus de vérifier si une propriété existe réellement ou non, car elle est toujours là, et ils peuvent simplement convertir la réponse en leur DTO personnalisé, en traitant lesnull
valeurs en option.Inclure / supprimer dynamiquement des champs des forces de réponse, y compris des conditions supplémentaires sur les clients.
Quoi qu'il en soit, quelle que soit la manière que vous choisissez, assurez-vous de la garder cohérente et bien documentée. De cette façon, peu importe ce que vous utilisez pour votre API, tant que le comportement est prévisible.
la source
null
pour les références. Le mélange de valeurs avec des références est une de mes préoccupations. Comment différenciez-vous les champs facultatifs des champsnull
de chaîne non facultatifs qui ont unenull
valeur? En analysant de nouveau, le fait de ne pas tester l'existence d'une propriété ne rend-il pas l'analyseur plus fragile?null
pour indiquer que la valeur est facultative. Ainsi, lorsque vous définissez un objet qui a une propriété de chaîne non facultative et que le consommateur n'a pas cette propriété, il doit envoyer une chaîne vide pour cette propriété. Est-ce correct?null
L'utilisation dépend de l'application / de la langueEn fin de compte, le choix d'utiliser ou non
null
comme valeur d'application valide est largement déterminé par votre application et votre langage de programmation / interface / périphérie.À un niveau fondamental, je recommanderais d'essayer d'utiliser des types distincts s'il existe des classes de valeurs distinctes.
null
peut être une option si votre interface le permet et qu'il n'y a que deux classes d'une propriété que vous essayez de représenter. L'omission d'une propriété peut être une option si votre interface ou votre format le permet. Un nouveau type d'agrégat (classe, objet, type de message) peut être une autre option.Pour votre exemple de chaîne, si c'est dans le langage de programmation, je me poserais quelques questions.
Option
sera probablement meilleur pour la conception de votre interface.Option
remplit probablement ce cas mieux si votre chaîne n'était pas nullable. Cependant, vous devrez probablement vérifier l'entrée de l'utilisateur pour unenull
valeur de chaîne de toute façon, alors je reviendrais probablement à la première ligne de questionnement: combien de types de valeurs je veux / veux-je représenter.null
indicative d'une erreur de programmation dans mon langage de programmation? Malheureusement, ilnull
s'agit souvent de la valeur par défaut pour les pointeurs ou références non initialisés (ou initialisés de manière non explicite) dans certaines langues. Lanull
valeur par défaut est-elle acceptable? Est-ce sûr comme valeur par défaut? Parfois, celanull
indique des valeurs désallouées. Dois-je fournir aux consommateurs de mon interface une indication de ces problèmes potentiels de gestion de la mémoire ou d'initialisation dans leur programme? Quel est le mode d'échec d'un tel appel face à de tels problèmes? L'appelant est-il dans le même processus ou thread que le mien afin que de telles erreurs soient un risque élevé pour mon application?En fonction de vos réponses à ces questions, vous pourrez probablement déterminer si cela convient ou non
null
à votre interface.Exemple 1
null
est une valeur de chaîne possible renvoyée en cas d'échec d'allocation d'espace pour une chaîne.Réponse:
null
n'est probablement pas appropriéJustification:
null
dans ce cas, est en fait utilisé pour indiquer deux types de valeurs différents. La première peut être une valeur par défaut que l'utilisateur de votre interface peut vouloir définir. Malheureusement, la deuxième valeur est un indicateur pour indiquer que votre système ne fonctionne pas correctement. Dans de tels cas, vous souhaitez probablement échouer de la manière la plus sûre possible (quoi que cela signifie pour votre système).Exemple 2
char *
membre.NULL
char *
membre de votre API peut être indiquée par une seule valeur deNULL
char *
membre.Réponse:
NULL
peut être appropriéJustification: Il y a un peu de chance que votre structure passe le
NULL
contrôle mais n'est pas initialisée. Cependant, votre API peut ne pas être en mesure de tenir compte de cela, sauf si vous avez une sorte de somme de contrôle sur la valeur de la structure et / ou la vérification de la plage de l'adresse de la structure. Les linters MISRA-C peuvent aider les utilisateurs de votre API en signalant l'utilisation des structures avant leur initialisation. Cependant, comme pour lechar *
membre, si le pointeur vers struct pointe vers une structure initialisée,NULL
est la valeur par défaut d'un membre non spécifié dans un initialiseur de structure. Par conséquent,NULL
peut servir de valeur par défaut sûre pour lechar *
membre struct dans votre application.Si c'est sur une interface de sérialisation, je me poserais les questions suivantes pour savoir si oui ou non utiliser null sur une chaîne.
null
indicative d'une erreur côté client potentiel? Pour JSON en JavaScript, il s'agit probablement d'un non car ilnull
n'est pas nécessairement utilisé comme indication d'un échec d'allocation. En JavaScript, il est utilisé comme une indication explicite de l'absence d'objet d'une référence à définir de manière problématique. Cependant, il existe des analyseurs et des sérialiseurs non javascript qui mappent JSONnull
aunull
type natif . Si tel est le cas, cela amène à discuter de la question de savoir si l'null
utilisation native est acceptable pour votre combinaison particulière de langue, analyseur et sérialiseur.null
indique en fait que vous avez un nouveau type de message entièrement. Il peut être plus simple pour vos consommateurs du format de sérialisation de simplement spécifier un type de message complètement différent. Cela garantit que leur validation et leur logique d'application peuvent avoir une séparation nette entre les deux distinctions de messages fournies par votre interface Web.Conseils généraux
null
ne peut pas être une valeur sur un bord ou une interface qui ne la prend pas en charge. Si vous utilisez quelque chose qui est extrêmement lâche dans la nature de la saisie de valeurs de propriétés (c'est-à-dire JSON), essayez de pousser une certaine forme de schéma ou de validation sur le logiciel de pointe des consommateurs (par exemple JSON Schema ) si vous le pouvez. S'il s'agit d'une API de langage de programmation, validez l'entrée utilisateur si possible statiquement (via la saisie) ou aussi fort que cela est sensé lors de l'exécution (alias pratiquez la programmation défensive sur les interfaces destinées aux consommateurs). Tout aussi important, documentez ou définissez le bord afin qu'il ne soit pas question de:la source
Voici mon analyse personnelle de ces questions. Il n'est soutenu par aucun livre, papier, étude ou autre, juste mon expérience personnelle.
Chaînes vides comme
null
C'est un pas pour moi. Ne mélangez pas la sémantique d'une chaîne vide avec celle d'une chaîne non définie. Dans de nombreux cas, ils peuvent être parfaitement interchangeables, mais vous pouvez rencontrer des cas où non définis et définis mais vides signifient quelque chose de différent.
Une sorte d'exemple stupide: disons qu'il y a un attribut qui stocke une clé étrangère, et cet attribut n'est pas défini ou l'est
null
, cela signifierait qu'il n'y a pas de relation définie, alors qu'une chaîne vide""
pourrait être comprise comme une relation définie et la L'ID de l'enregistrement étranger est cette chaîne vide.Non défini vs
null
Ce n'est pas un sujet noir ou blanc. Les deux approches présentent des avantages et des inconvénients.
En faveur d'une définition explicite des
null
valeurs, il y a ces avantages:En faveur de l'hypothèse qu'une clé non existante est égale à la sémantique de
null
:Dans le cas où l'API est en quelque sorte stable et que vous la documentez à fond, je pense qu'il est parfaitement correct de déclarer qu'une clé inexistante équivaut à la signification de
null
. Mais si c'est plus compliqué et chaotique (comme c'est souvent le cas), je pense que vous pouvez éviter les maux de tête si vous définissez explicitement chaque valeur dans chaque message. C'est-à-dire qu'en cas de doute, j'ai tendance à suivre l'approche verbeuse.Cela dit, la chose la plus importante: énoncez clairement vos intentions et soyez cohérent. Ne faites pas une chose ici et l'autre là-bas. Un logiciel prévisible est un meilleur logiciel.
la source
null
. Autre exemple: dans un jeu, il y a un objet personnage, et il a un attribut "partenaire". Unnull
partenaire signifie clairement qu'il n'y a pas de partenaire du tout, mais""
peut être compris comme il y a un partenaire dont le nom est""
.null
pour une chaîne vide. Peut-être le rendre sous une forme, mais jamais dans le modèle de données.name
dont je parlais, autoriseriez-vous le nom du partenaire à être nul?Je fournirais une chaîne vide dans une situation où une chaîne est présente, et il se trouve que c'est une chaîne vide. Je fournirais null dans une situation où je voudrais dire explicitement "non, ces données ne sont pas là". Et omettez la clé pour dire "pas de données là-bas, ne vous embêtez pas".
Vous jugez laquelle de ces situations peut se produire. Est-il logique que votre application ait des chaînes vides? Voulez-vous faire la distinction entre dire explicitement «pas de données» en utilisant null et implicitement sans valeur? Vous ne devriez avoir les deux possibilités (null et aucune clé présente) si les deux doivent être distinguées par le client.
Gardez maintenant à l'esprit qu'il s'agit de transmettre des données. Ce que le destinataire fait des données, c'est son entreprise, et il fera ce qui lui convient le mieux. Le récepteur doit être capable de gérer tout ce que vous lui lancez (éventuellement en rejetant les données) sans planter.
S'il n'y a pas d'autres considérations, je transmettrais ce qui convient le mieux à l'expéditeur et le documenterai . Je préfère ne pas envoyer de valeurs absentes du tout, car cela améliorera probablement la vitesse d'encodage, de transmission et d'analyse JSON.
la source
Bien que je ne puisse pas dire ce qui est le mieux, ce n'est certainement pas un simple détail d'implémentation , cela change la structure de la façon dont vous pouvez interagir avec cette variable.
Si quelque chose peut être nul, vous devez toujours le traiter comme s'il le serait à un moment donné , vous aurez donc toujours deux workflows , un pour null, un pour une chaîne valide. Un flux de travail fractionné n'est pas nécessairement une mauvaise chose, car il y a beaucoup de gestion des erreurs et des utilisations spéciales que vous pouvez utiliser, mais il obscurcit votre code.
Si vous interagissez toujours avec la chaîne de la même manière, il sera probablement plus facile pour la fonctionnalité de rester dans votre tête .
Donc, comme pour toute question «ce qui est le mieux», il me reste la réponse: cela dépend . Si vous souhaitez diviser votre flux de travail et capturer plus explicitement lorsque quelque chose n'est pas défini, utilisez null. Si vous préférez que le programme continue de faire comme il le fait, utilisez une chaîne vide. L'important est que vous soyez cohérent , choisissez un rendement commun et respectez-le.
Étant donné que vous créez une API, je vous recommande de vous en tenir à une chaîne vide car il y a moins pour l'utilisateur à compenser, car en tant qu'utilisateur d'une API, je ne connais pas toutes les raisons pour lesquelles votre API pourrait me donner une valeur nulle, sauf si vous '' re très bien documenté, que certains utilisateurs ne liront pas de toute façon.
la source
string
s, jamais null. Si l'API utilise null, le producteur doit à un moment donné le créernull
pour se conformer à l'API. Ensuite, le consommateur doitnull
également gérer . Mais je pense avoir compris ce que vous dites, il suffit de décider et de définir l'API avec autorité, non? Est-ce à dire qu'il n'y a rien de mal à aucun d'entre eux?Document!
TL; DR>
Faites comme bon vous semble - parfois le contexte dans lequel il est utilisé est important. Exemple, lier des variables à un SQL Oracle: une chaîne vide est interprétée comme un NULL.
Je dirais simplement - Assurez-vous de documenter chaque scénario mentionné
Votre code peut agir de différentes manières: documentez la réaction de votre code:
Ensuite, en plus de cela - c'est à vous de vous comporter de manière cohérente, et éventuellement d'adopter certaines de vos meilleures pratiques. Documentez ce comportement cohérent. Exemples:
la source
tl; dr - si vous l'utilisez: soyez cohérent dans ce que cela signifie.
Si vous incluez
null
, qu'est-ce que cela signifie? Il y a un univers de choses ce que cela pourrait signifier. Une valeur n'est tout simplement pas suffisante pour représenter une valeur manquante ou inconnue (et ce ne sont que deux de la myriade de possibilités: par exemple manquant - il a été mesuré, mais nous ne le savons pas encore. Inconnu - nous n'avons pas essayé de mesurer il.)Dans un exemple que j'ai rencontré récemment, un champ peut être vide car il n'a pas été signalé pour protéger la vie privée de quelqu'un, mais il était connu du côté de l'expéditeur, inconnu du côté de l'expéditeur, mais connu du journaliste d'origine ou inconnu des deux. Et tout cela comptait pour le récepteur. Donc, généralement, une seule valeur ne suffit pas.
Avec une hypothèse de monde ouvert (vous ne savez tout simplement pas sur les choses non énoncées), vous laisseriez simplement de côté et cela pourrait être n'importe quoi. Avec l'hypothèse du monde fermé (les choses non énoncées sont fausses, par exemple en SQL), vous feriez mieux de préciser ce que
null
signifie et d'être aussi cohérent avec cette définition que possible ...la source