2012-07-27 17 views
8

Tengo una cadena que representa JSON y quiero cambiar el nombre de algunas de las propiedades usando JSON.NET. Necesito una función genérica para usar para cualquier JSON. Algo como:Propiedades de cambio de nombre de Json.net

public static void Rename(JContainer container, Dictiontionary<string, string> mapping) 
{ 
    foreach (JToken el in container.Children()) 
    { 
    JProperty p = el as JProperty; 
    if(el != null && mapping.ContainsKey(p.Name)) 
    { 
     // **RENAME THIS NODE!!** 
    } 

    // recursively rename nodes 
    JContainer pcont = el as JContainer; 
    if(pcont != null) 
    { 
     Rename(pcont, mapping); 
    } 
    } 
} 

¿Cómo hacerlo?

Respuesta

13

Sugeriría reconstruir su JSON con propiedades renombradas. No creo que deba preocuparse por las penalizaciones de velocidad, ya que generalmente no es un problema. Así es como puedes hacerlo.

public static JToken Rename(JToken json, Dictionary<string, string> map) 
{ 
    return Rename(json, name => map.ContainsKey(name) ? map[name] : name); 
} 

public static JToken Rename(JToken json, Func<string, string> map) 
{ 
    JProperty prop = json as JProperty; 
    if (prop != null) 
    { 
     return new JProperty(map(prop.Name), Rename(prop.Value, map)); 
    } 

    JArray arr = json as JArray; 
    if (arr != null) 
    { 
     var cont = arr.Select(el => Rename(el, map)); 
     return new JArray(cont); 
    } 

    JObject o = json as JObject; 
    if (o != null) 
    { 
     var cont = o.Properties().Select(el => Rename(el, map)); 
     return new JObject(cont); 
    } 

    return json; 
} 

Y aquí es un ejemplo de uso:

var s = @"{ ""A"": { ""B"": 1, ""Test"": ""123"", ""C"": { ""Test"": [ ""1"", ""2"", ""3"" ] } } }"; 
var json = JObject.Parse(s); 

var renamed = Rename(json, name => name == "Test" ? "TestRenamed" : name); 
renamed.ToString().Dump(); // LINQPad output 

var dict = new Dictionary<string, string> { { "Test", "TestRenamed"} }; 
var renamedDict = Rename(json, dict); 
renamedDict.ToString().Dump(); // LINQPad output 
+0

Gracias Dmitry, esto es perfecto! –

+0

Puede haber algunos errores menores, pero puede solucionarlos usted mismo si encuentra alguno :) –

3

Utilizamos este enfoque. Puede encontrar la propiedad que desea utilizando JObject's SelectToken(). Sí, admite JsonPath.

public static class NewtonsoftExtensions 
{ 
    public static void Rename(this JToken token, string newName) 
    { 
     var parent = token.Parent; 
     if (parent == null) 
      throw new InvalidOperationException("The parent is missing."); 
     var newToken = new JProperty(newName, token); 
     parent.Replace(newToken); 
    } 
} 
+0

Un poco sorprendido de que no haya señalado que esto es realmente parte del marco, obtenido por usted: https://github.com/abibell /Newtonsoft.Json/commit/12f3f32401074a84b3d186956e59e56c9e8781cb :-) –

+0

Hola Alastair, quería la función. Hice cambios de café y envié una solicitud de extracción. No fue aceptado por el propietario con un motivo "No me gusta" .https: //github.com/JamesNK/Newtonsoft.Json/pull/549 –

+1

@AbiBellamkonda, estoy intentando usar este método de extensión para cambie el nombre de un objeto JProperty, pero obtengo la excepción "No se puede agregar Newtonsoft.Json.Linq.JProperty a Newtonsoft.Json.Linq.JProperty". de este código: 'nuevo JProperty (newName, token)'. – Gyromite

Cuestiones relacionadas