7
votes

TypenameHandling in Newtonsoft nécessite $ Type pour être la première propriété?

J'ai la méthode suivante dans mon API Web

{
 "$type": "BrickPile.Samples.Models.Article, BrickPile.Samples",
  "id": "articles/1",
  "heading": "Bar" 
}


3 commentaires

Regardez la réponse de @ Levi, il est le gars de sécurité de l'équipe Web.


C'est totalement fou qu'il fonctionne de cette façon dans Json.Net et Microsofts stuff intégré ... Dans de nombreuses bibliothèques JSON, comme Jackson en Java, il n'est pas garanti que la carte (que vous pouvez construire à Jackson) est commandée. En fait, c'est une carte, et donc aucun ordre n'est maintenu. Donc, vous n'avez aucun contrôle de l'endroit où le type $ ou __TYPE apparaît dans le JSON. Parfois, cela d'abord, et travaille, parfois ce n'est pas. Ainsi, il est impossible de truter cette fonctionnalité ...


Ceci est une erreur de type de base dans la bibliothèque. Si la bibliothèque veut compter sur la commande, elle doit utiliser un type de données commandé, par exemple. Un tableau de 2 éléments, où le premier élément était le nom de la classe Serialized et le deuxième élément des données d'objet. Un objet JSON est par définition non ordonnée, de sorte que c'est maintenant un bogue dans la bibliothèque.


4 Réponses :


1
votes

Cela fonctionnera dans la colonne vertébrale, mais je ne sais pas si chaque navigateur se comportera de la même manière. Il n'y a pas de garantie, fondamentalement, que chaque navigateur conserve les articles dans l'ordre dans lequel ils sont ajoutés.

MyModel = Backbone.Model.extend({

  // ...

  toJSON: function(){
    // build the "$type" as the first parameter
    var json = {"$type": "BrickPile.Samples.Models.Article, BrickPile.Samples"};
    // get the rest of the data
    _.extend(json, Backbone.Model.prototype.toJSON.call(this));
    // send it back, and hope it's in the right order
    return json;
  }


});


3 commentaires

Cela a fonctionné plutôt bien, la propriété $ est déjà existante dans le modèle de colonne vertébrale, alors est-il possible de "brique.samples.models.article, de briques.samples" du modèle actuel au lieu d'un code dur la chaîne?


Je suppose que cela.get ('$ type') fera le tour


Borth DatacontractSerializer (Microsoft) et Json.net exigent que la première propriété Type (ou __TYPE in MS) soit la première propriété, sinon elle échouera Epic. Pourquoi c'est comme ça est complètement incompréhensible, mais c'est comme ça que c'est ...



4
votes

Je recommanderais très fortement à la configuration de tout sérieliseur (y compris JSON.net) pour lire le type d'objet à partir de la charge utile entrante. Cela a toujours été la cause d'un grand nombre de vulnérabilités dans les applications Web. Au lieu de cela, changez le point d'entrée public vers votre action pour prendre le type réel en tant que paramètre lié, puis déléguer à une méthode interne testable si vous le souhaitez.


1 commentaires

Mon problème est que je ne connais pas le type actuel, la seule chose que je sais, c'est que cela implémente l'interface iconent. Je peux aussi dire que ce n'est pas une API publique, cela nécessite que vous soyez authentifié.



3
votes

Premier, Afaik, le code de JSON.NET est optimisé pour éviter de contenir l'objet entier dans la mémoire simplement pour lire son type. Donc, il vaut mieux placer $ Tapez comme première propriété.

Deuxièmement, vous pouvez écrire votre propre jsonconverter qui lit d'abord à jobject (à l'aide de charger méthode), lit manuellement $ Type Propriété, reçoit Type de Serializer's SerializationBinder , crée la valeur et la populaire de Jobject .

Troisième, en ce qui concerne la sécurité. Tandis que JSON.net's's $ Type peut sembler une bonne idée, ce n'est souvent pas. Il permet à JSON.net de créer tout type d'objet de Assembly en écrivant son type dans le fichier JSON. Il est préférable d'utiliser personnalisé SerializationBinder avec un dictionnaire qui ne permet que des types que vous spécifiez. Vous pouvez trouver un exemple dans mon cadre privé (il prend également en charge l'obtention de valeurs pour $ Type à partir de JSONOBJETTRIBUTE ):

https://github.com/ Athari / alba.framework / BLOB / 742FF1AEEB114179A16CA42667781944266778194446677815 / Alba.framework / Serialization / DictionnaireSerializationBinder.cs

(Cette version utilise certaines méthodes d'autres classes, mais elles sont triviales. Les commits plus tard rendent la classe plus complexe.)


1 commentaires

Merci pour votre réponse, je vais regarder votre code!



2
votes

J'ai eu une sorte de la même question apparemment, et quelqu'un a trouvé une réponse. Je ne sais pas ce qui est le moyen approprié de partager une réponse et de lui donner tout le crédit, mais c'est le lien: Newtonsoft JSON.net désérialisation erreur où les champs de la commande JSON changent

Et c'est le gars: https://stackoverflow.com/users/3744182/dbc


1 commentaires

Merci beaucoup. C'est la meilleure solution.