2012-07-27 19 views
8

Mam ciąg reprezentujący JSON i chcę zmienić nazwę niektórych właściwości za pomocą JSON.NET. Potrzebuję ogólnej funkcji do użycia dla dowolnego JSON. Coś jak:Właściwości zmiany nazwy 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); 
    } 
    } 
} 

Jak to zrobić?

Odpowiedz

13

Sugerowałbym rekonstrukcję twojego JSON z przemianowanymi właściwościami. Nie sądzę, że powinieneś martwić się karami prędkości, ponieważ zazwyczaj nie jest to problemem. Oto, jak możesz to zrobić.

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; 
} 

A oto przykład użycia:

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

Dzięki Dmitry, to jest idealne! –

+0

Może być kilka drobnych błędów, ale możesz je naprawić samemu, jeśli znajdziesz jakieś :) –

3

Używamy tego podejścia. Możesz znaleźć właściwość, którą chcesz, używając JObject's SelectToken(). Tak, obsługuje on 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

Lekko zaskoczony, nie zauważyłeś, że jest to część struktury, wyładowanej przez ciebie: https://github.com/abibell /Newtonsoft.Json/commit/12f3f32401074a84b3d186956e59e56c9e8781cb :-) –

+0

Cześć Alastair, chciałem funkcję. Wprowadziłem zmiany w kawie i wysłałem prośbę o wyciągnięcie. Nie został zaakceptowany przez właściciela z powodu "Nie podoba mi się to" .https: //github.com/JamesNK/Newtonsoft.Json/pull/549 –

+1

@AbiBellamkonda, Próbuję użyć tej metody rozszerzenia do zmień nazwę obiektu JProperty, ale otrzymuję wyjątek "Nie można dodać Newtonsoft.Json.Linq.JProperty do Newtonsoft.Json.Linq.JProperty." z tego fragmentu kodu: 'new JProperty (newName, token)'. – Gyromite

Powiązane problemy