web-dev-qa-db-fra.com

Comment ajoutez-vous un JToken à un JObject?

J'essaie d'ajouter un objet JSON d'un texte à un fichier JSON existant à l'aide de JSON.Net. Par exemple, si j'ai les données JSON ci-dessous:

  {
  "food": {
    "fruit": {
      "Apple": {
        "colour": "red",
        "size": "small"
      },
      "orange": {
        "colour": "orange",
        "size": "large"
      }
    }
  }
}

J'ai essayé de faire ça comme ça:

var foodJsonObj = JObject.Parse(jsonText);
var bananaJson = JObject.Parse(@"{ ""banana"" : { ""colour"": ""yellow"", ""size"": ""medium""}}");
var bananaToken = bananaJson as JToken;
foodJsonObj["food"]["fruit"]["orange"].AddAfterSelf(bananaToken);

Mais cela donne l'erreur: "Newtonsoft.Json.Linq.JProperty cannot have multiple values."

En fait, j'ai essayé plusieurs méthodes mais je n'arrive pas à aller nulle part. Dans mon exemple, ce que je veux vraiment faire, c'est ajouter le nouvel élément à "fruit". S'il vous plaît laissez-moi savoir s'il existe une meilleure façon de faire cela ou une bibliothèque plus simple à utiliser.

73
Jim

Je pense que vous avez du mal à comprendre ce qui peut contenir quoi dans JSON.Net.

  • Un JToken est une représentation générique d'une valeur JSON de tout type. Ce pourrait être une chaîne, un objet, un tableau, une propriété, etc.
  • Un JProperty est une seule valeur JToken associée à un nom. Il ne peut être ajouté qu'à JObject, et sa valeur ne peut pas être une autre JProperty.
  • Un JObject est une collection de JProperties. Il ne peut contenir aucun autre type de JToken directement.

Dans votre code, vous essayez d’ajouter un JObject (celui contenant les données "banane") à un JProperty ("orange") qui a déjà une valeur (un JObject contenant {"colour":"orange","size":"large"}). Comme vous l'avez vu, cela entraînera une erreur.

Ce que vous voulez vraiment faire est d’ajouter un JProperty appelé "banane" au JObject qui contient l’autre fruit JProperties. Voici le code révisé:

JObject foodJsonObj = JObject.Parse(jsonText);
JObject fruits = foodJsonObj["food"]["fruit"] as JObject;
fruits.Add("banana", JObject.Parse(@"{""colour"":""yellow"",""size"":""medium""}"));
121
Brian Rogers

TL; DR: Vous devez ajouter une JProperty à un objet JO. Facile. La requête d'index retourne une JValue, alors cherchez comment obtenir le JProperty à la place :)


La réponse acceptée ne répond pas à la question comme il semble. Et si je veux ajouter spécifiquement un JProperty après un spécifique? Tout d’abord, commençons par les terminologies qui ont vraiment agi ma tête.

  • JToken = La mère de tous les autres types. Ce peut être A JValue, JProperty, JArray ou JObject. Cela permet de fournir une conception modulaire au mécanisme d'analyse.
  • JValue = tout type de valeur Json (string, int, boolean).
  • JProperty = tout JValue ou JContainer (voir ci-dessous) associé à un nom (identifiant) . Par exemple "name":"value".
  • JContainer = La mère de tous les types qui contient d'autres types (JObject, JValue).
  • JObject = un type JContainer contenant une collection de JProperties
  • JArray = un type JContainer qui contient une collection JValue ou JContainer.

Désormais, lorsque vous interrogez un élément Json à l'aide de l'index [], vous obtenez JToken sans l'identifiant, qui peut être un JContainer ou un JValue (nécessite un casting), mais vous ne pouvez rien ajouter après, car il ne s'agit que d'une valeur. Vous pouvez le modifier lui-même, interroger des valeurs plus profondes, mais vous ne pouvez rien ajouter après, par exemple.

Ce que vous voulez réellement obtenir est la propriété dans son ensemble, puis ajoutez une autre propriété après comme souhaité. Pour cela, vous utilisez JOjbect.Property("name"), puis vous créez une autre propriété JP de votre choix, puis vous l'ajoutez ensuite à l'aide de la méthode AddAfterSelf. Vous avez terminé alors.

Pour plus d'informations: http://www.newtonsoft.com/json/help/html/ModifyJson.htm

C'est le code que j'ai modifié.

public class Program
{
  public static void Main()
  {
    try
    {
      string jsonText = @"
      {
        ""food"": {
          ""fruit"": {
            ""Apple"": {
              ""colour"": ""red"",
              ""size"": ""small""
            },
            ""orange"": {
              ""colour"": ""orange"",
              ""size"": ""large""
            }
          }
        }
      }";

      var foodJsonObj = JObject.Parse(jsonText);
      var bananaJson = JObject.Parse(@"{ ""banana"" : { ""colour"": ""yellow"", ""size"": ""medium""}}");

      var fruitJObject = foodJsonObj["food"]["fruit"] as JObject;
      fruitJObject.Property("orange").AddAfterSelf(new JProperty("banana", fruitJObject));

      Console.WriteLine(foodJsonObj.ToString());
    }
    catch (Exception ex)
    {
      Console.WriteLine(ex.GetType().Name + ": " + ex.Message);
    }
  }
}
31
Ghasan

Il suffit d'ajouter .First à votre bananaToken devrait le faire:
foodJsonObj["food"]["fruit"]["orange"].Parent.AddAfterSelf(bananaToken.First);
.First va essentiellement au-delà de { pour en faire un JProperty au lieu d'un JToken.

@ Brian Rogers, Merci j'ai oublié le .Parent. Édité

5
RepDbg