2013-01-19 9 views
8

Chciałbym przekonwertować ciąg JSONC# Sortowanie JSON klucze łańcuchowe

"{ \"birthday\": \"1988-03-18\", \"address\": { \"state\": 24, \"city\": 8341, \"country\": 1 } }" 

do

"{ \"address\": { \"city\": 8341, \"country\": 1, \"state\": 24 }, \"birthday\": \"1988-03-18\" }" 

UWAGA: Nie używam posortowane wersję dla komunikacji (ponieważ klucz robi porządek to naprawdę ważne), potrzebuję posortowaną wersję do wykonania testów lokalnych (przez porównanie napisów JSON).


EDIT: I4V wskazał rozwiązanie, które wykorzystuje Json.Net, wolałbym użyć rozwiązanie, które nie wymaga obejmować dowolną 3rd biblioteki strona (faktycznie używam wbudowanego w System.Json w moim aplikacja)


Zamieściłem sens z roztworem dostarczonych przez I4V + kilka testów here. Dziękuję wam wszystkim.

+0

Hmm ... Kuszące, choć brzmi, bym się zaryzykował, że lepszym rozwiązaniem byłoby nieco głębsza inspekcja JSON, a nie porównanie kawałków. Biorąc pod uwagę, że wyliczanie właściwości w JS nie jest określone przez specyfikację, nie należy polegać na kolejności właściwości obiektu, ponieważ nie ma sensu zamawianie właściwości serializacji json. ECMA-262, sekcja 12.6.4: Mechanika wyliczania właściwości ... jest zależna od implementacji. – spender

+0

@spender Zgadzam się z tobą, że kolejność kluczy JSON jest bez znaczenia, a porównywanie ciągów nie powinno być używane do porównywania dużych/złożonych obiektów JSON. Ale sorter ciągów JSON może być przydatny w bardzo specyficznych sytuacjach (takich jak moje). –

Odpowiedz

10

użyję Json.Net tego

string json = @"{ ""birthday"": ""1988-03-18"", ""address"": { ""state"": 24, ""city"": 8341, ""country"": 1 } }"; 
var jObj = (JObject)JsonConvert.DeserializeObject(json); 
Sort(jObj); 
string newJson = jObj.ToString(); 

void Sort(JObject jObj) 
{ 
    var props = jObj.Properties().ToList(); 
    foreach (var prop in props) 
    { 
     prop.Remove(); 
    } 

    foreach (var prop in props.OrderBy(p=>p.Name)) 
    { 
     jObj.Add(prop); 
     if(prop.Value is JObject) 
      Sort((JObject)prop.Value); 
    } 
} 

EDIT

spróbować z System.Json ale nie jestem pewien o OrderByDescending (lub OrderBy).

var jObj = (System.Json.JsonObject)System.Json.JsonObject.Parse(json); 
Sort2(jObj); 
var newJson = jObj.ToString(); 

void Sort2(System.Json.JsonObject jObj) 
{ 
    var props = jObj.ToList(); 
    foreach (var prop in props) 
    { 
     jObj.Remove(prop.Key); 
    } 

    foreach (var prop in props.OrderByDescending(p => p.Key)) 
    { 
     jObj.Add(prop); 
     if (prop.Value is System.Json.JsonObject) 
      Sort2((System.Json.JsonObject)prop.Value); 
    } 
} 
+0

Interesujące. Ale używam wbudowanego systemu.Json w mojej aplikacji, więc wolałbym używać rozwiązania, które nie wymaga biblioteki innej firmy. –

+0

Czy chcesz usunąć właściwości z JObj, a nie z listy właściwości? Wygląda na to, że usuwasz wszystkie elementy z listy właściwości, a następnie próbujesz je sortować i wyliczyć. – Despertar

+0

Ja zredagowałem moje pytanie z tobą rozwiązanie i moje ograniczenia –

2

Korzystając this approach you can retrieve a dynamic object with your json data

Na DynamicJsonConverter stworzyć SortedDictionary zamiast

var d = new SortedDictionary<string, object>(dictionary); 
// TODO: code to sort inner objects 
return new DynamicJsonObject(d); 

Następnie można użyć

string jsonStr = "{\"B\":\"2\",\"A\":\"1\"}"; 
JavaScriptSerializer jss = new JavaScriptSerializer(); 
jss.RegisterConverters(new JavaScriptConverter[] { new DynamicJsonConverter() }); 

dynamic json = jss.Deserialize(jsonStr, typeof(object)) as dynamic; 

string result = new JavaScriptSerializer().Serialize((json as DynamicJsonObject).Dictionary); 

I result będzie miał oczekiwany wynik.

+1

Dzięki @BrunoLM, jednak skończyło się na użyciu prostego 'System.Json.JsonObject'. –

0

wiem, to może być trochę za późno, ale w przypadku trzeba uporządkować wewnętrzne tablice danych zbyt (ja po prostu potrzebował):

static void Sort(JObject jObj) 
{ 
    var props = jObj.Properties().ToList(); 
    foreach (var prop in props) 
    { 
     prop.Remove(); 
    } 

    foreach (var prop in props.OrderBy(p => p.Name)) 
    { 
     jObj.Add(prop); 
     if (prop.Value is JObject) 
      Sort((JObject)prop.Value); 
     if (prop.Value is JArray) 
     { 
      Int32 iCount = prop.Value.Count(); 
      for (Int32 iIterator = 0; iIterator < iCount; iIterator++) 
       if (prop.Value[iIterator] is JObject) 
        Sort((JObject)prop.Value[iIterator]); 
     } 
    } 
} 

Cheers!