2012-07-27 5 views
8

JSONを表す文字列があり、JSON.NETを使用していくつかのプロパティの名前を変更したいとします。任意のJSONに使用する汎用関数が必要です。次のようなもの: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); 
    } 
    } 
} 

どのようにすればいいですか?

答えて

13

名前を変更したプロパティでJSONを再構築することをお勧めします。私はあなたが通常は問題ではないので、スピードのペナルティについて心配する必要はないと思う。あなたがそれを行う方法は次のとおりです。

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

そして、ここでの使用例です:

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

ありがとうドミトリー、これは完璧です! –

+0

マイナーなバグがあるかもしれませんが、見つけたら自分で修正することができます:) –

3

私たちは、このアプローチを使用しています。 JObjectのSelectToken()を使用して、必要なプロパティを見つけることができます。はい、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

これは実際にフレームワークの一部であり、https://github.com/abibell /Newtonsoft.Json/commit/12f3f32401074a84b3d186956e59e56c9e8781cb :-) –

+0

こんにちはAlastair、私はこの機能を望んでいました。私はコーヒーの交換をしてプルリクエストを送った。 "私はそれが好きではない"という理由でオーナーに受け入れられませんでした.https://github.com/JamesNK/Newtonsoft.Json/pull/549 –

+1

@AbiBellamkonda、私はこの拡張メソッドを使用しようとしていますJPropertyオブジェクトの名前を変更しますが、「Newtonsoft.Json.Linq.JPropertyをNewtonsoft.Json.Linq.JPropertyに追加できません」という例外が表示されます。この新しいコードから、 '新しいJProperty(newName、token)'。 – Gyromite

関連する問題