Eduardo Coelho
Eduardo Coelho

Reputation: 1963

C# Sort JSON string keys

I'd like to convert the JSON string

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

to

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

NOTE: I'm not using the sorted version for communication (because the key order doesn't really matter), I need a sorted version to perform local tests (by comparing JSON strings).


EDIT: I4V pointed a solution that uses Json.Net, I would rather use a solution that doesn't need to include any 3rd party library (actually I'm using the built in System.Json in my application)


I posted a gist with the solution provided by I4V + some testing here. Thank you all.

Upvotes: 9

Views: 21408

Answers (4)

MrD at KookerellaLtd
MrD at KookerellaLtd

Reputation: 2795

I wanted to sort contents of an array (not the array itself) and missed someone had done it above,

This ones functional, it clones the JSON

static JToken SortFunctional(JToken jt)
{
    if (jt is JObject)
    {
        var jo = (JObject)jt;
        var children =
            from p in jo.Properties()
            orderby p.Name
            select SortFunctional(p);
        return new JObject(children);
    }
    else if (jt is JArray)
    {
        var ja = (JArray)jt;
        var newElements =
            from e in ja
            select SortFunctional(e);
        return new JArray(newElements);
    }
    else if (jt is JProperty)
    {
        var jp = (JProperty)jt;
        return new JProperty(jp.Name,SortFunctional(jp.Value)); 
    }
    else
    {
        // presumably JValue
        return jt.DeepClone();
    }
}

I've used it for about 10 mins, it seems to work, but there maybe some weirdness in there.

Upvotes: 0

imnotaduck
imnotaduck

Reputation: 197

I know this may be a little late but, in case of you need to sort the internal arrays of data too (I just needed it):

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!

Upvotes: 6

BrunoLM
BrunoLM

Reputation: 100351

By using this approach you can retrieve a dynamic object with your json data

At the DynamicJsonConverter create a SortedDictionary instead

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

Then you can use

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

And result will have the expected output.

Upvotes: 3

I4V
I4V

Reputation: 35353

I will use Json.Net for this

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

A try with System.Json but I am not sure about OrderByDescending ( or 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);
    }
}

Upvotes: 20

Related Questions