2012-07-27 21 views
8

Tôi có một chuỗi đại diện cho JSON và tôi muốn đổi tên một số thuộc tính bằng JSON.NET. Tôi cần một hàm chung để sử dụng cho bất kỳ JSON nào. Một cái gì đó như:Tính năng đổi tên 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ách thực hiện?

Trả lời

13

Tôi sẽ đề xuất xây dựng lại JSON của bạn với các thuộc tính được đổi tên. Tôi không nghĩ rằng bạn nên lo lắng về tốc độ phạt vì nó thường không phải là một vấn đề. Đây là cách bạn có thể làm điều đó.

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

Và đây là một ví dụ về việc sử dụng:

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

Cảm ơn Dmitry, điều này thật hoàn hảo! –

+0

Có thể có một số lỗi nhỏ nhưng bạn có thể sửa chúng nếu bạn tìm thấy bất kỳ :) –

3

Chúng tôi sử dụng phương pháp này. Bạn có thể tìm thuộc tính bạn muốn bằng cách sử dụng SelectToken() của JObject. Có nó không hỗ trợ 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

Hơi ngạc nhiên khi bạn không chỉ ra rằng đây thực sự là một phần của khung công tác, do bạn: https://github.com/abibell /Newtonsoft.Json/commit/12f3f32401074a84b3d186956e59e56c9e8781cb :-) –

+0

Xin chào Alastair, tôi muốn tính năng này. Tôi đã thay đổi cà phê cho nó và gửi một yêu cầu kéo. Nó không được chủ sở hữu chấp nhận với lý do "Tôi không thích nó" .https: //github.com/JamesNK/Newtonsoft.Json/pull/549 –

+1

@AbiBellamkonda, tôi đang cố gắng sử dụng phương pháp mở rộng này để đổi tên một đối tượng JProperty, nhưng tôi có ngoại lệ "Không thể thêm Newtonsoft.Json.Linq.JProperty vào Newtonsoft.Json.Linq.JProperty." từ bit mã này: 'new JProperty (newName, token)'. – Gyromite

Các vấn đề liên quan