c# - newtonsoft - ¿Cómo se agrega un JToken a JObject?
newtonsoft json documentation (3)
Estoy tratando de agregar un objeto JSON de un texto a un archivo JSON existente usando JSON.Net. Por ejemplo, si tengo los datos JSON de la siguiente manera:
{
"food": {
"fruit": {
"apple": {
"colour": "red",
"size": "small"
},
"orange": {
"colour": "orange",
"size": "large"
}
}
}
}
He estado tratando de hacer esto así:
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);
Pero esto da el error: "Newtonsoft.Json.Linq.JProperty cannot have multiple values."
De hecho, he intentado de diferentes maneras, pero parece que no puedo llegar a ninguna parte. En mi ejemplo, lo que realmente quiero hacer es agregar el nuevo elemento a "fruta". Por favor, avíseme si hay una mejor manera de hacerlo o una biblioteca más simple de usar.
Creo que te estás confundiendo acerca de qué puede contener qué en JSON.Net.
- A
JToken
es una representación genérica de un valor JSON de cualquier tipo. Podría ser una cadena, un objeto, una matriz, una propiedad, etc. - Un
JProperty
es un solo valorJToken
emparejado con un nombre. Solo se puede agregar aJObject
y su valor no puede ser otroJProperty
. - Un
JObject
es una colección deJProperties
. No puede contener ningún otro tipo deJToken
directamente.
En su código, está intentando agregar un JObject
(el que contiene los datos "banana") a un JProperty
("orange") que ya tiene un valor (un JObject
contiene {"colour":"orange","size":"large"}
). Como viste, esto dará como resultado un error.
Lo que realmente quieres hacer es agregar un JProperty
llamado "banana" al JObject
que contiene las otras frutas JProperties
. Aquí está el código revisado:
JObject foodJsonObj = JObject.Parse(jsonText);
JObject fruits = foodJsonObj["food"]["fruit"] as JObject;
fruits.Add("banana", JObject.Parse(@"{""colour"":""yellow"",""size"":""medium""}"));
Solo agregue. .First
a su bananaToken
debería hacerlo:
foodJsonObj["food"]["fruit"]["orange"].Parent.AddAfterSelf(bananaToken
.First
);
.First
básicamente pasa del {
para convertirlo en JProperty
lugar de JToken
.
@Brian Rogers, gracias, olvidé el .Parent
. Editado
TL; DR: Debería agregar una JProperty a JObject. Sencillo. La consulta de índice devuelve un JValue, así que averigua cómo obtener el JProperty en su lugar :)
La respuesta aceptada no responde la pregunta como parece. ¿Qué sucede si quiero agregar específicamente JProperty después de uno específico? Primero, comencemos con terminologías que realmente me hicieron pensar.
- JToken = La madre de todos los demás tipos. Puede ser A JValue, JProperty, JArray o JObject. Esto es para proporcionar un diseño modular al mecanismo de análisis sintáctico.
- JValue = cualquier tipo de valor Json (string, int, boolean).
- JProperty = cualquier JValue o JContainer (ver a continuación) emparejado con un nombre (identificador) . Por ejemplo,
"name":"value"
. - JContainer = La madre de todos los tipos que contienen otros tipos (JObject, JValue).
- JObject = un tipo JContainer que contiene una colección de JProperties
- JArray = un tipo JContainer que contiene una colección JValue o JContainer.
Ahora, cuando consulta el elemento Json utilizando el índice [], obtiene el JToken sin el identificador, que podría ser un JContainer o un JValue (requiere conversión), pero no puede agregar nada después de él, porque es solo un valor. Puede cambiarlo por sí mismo, consultar valores más profundos, pero no puede agregar nada después de eso, por ejemplo.
Lo que realmente desea obtener es la propiedad como un todo, y luego agregue otra propiedad después de ella como lo desee. Para esto, usas JOjbect.Property("name")
, y luego creas otro JProperty de tu deseo y luego lo agregas después de esto usando el método AddAfterSelf
. Has terminado entonces.
Para más información: http://www.newtonsoft.com/json/help/html/ModifyJson.htm
Este es el código que modifiqué.
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);
}
}
}