Reputation: 90
I have a JSON string like this:
{
"name": "NameOfObject",
"itemsToSort": [
{
"name": "ValueB",
"someProperty": "SomeValue"
},
{
"name": "ValueA",
"someProperty": "SomeValue"
},
{
"name": "ValueC",
"someProperty": "SomeValue"
}
],
"someThing": [
{
"name": "ThingB",
"anotherProperty": "SomeValue"
},
{
"name": "ThingA",
" anotherProperty": "SomeValue "
}
]
}
I need to sort only the itemsToSort element alphabetically in C#, so it looks like this:
{
"name": "NameOfObject",
"itemsToSort": [
{
"name": "ValueA",
"someProperty": "SomeValue"
},
{
"name": "ValueB",
"someProperty": "SomeValue"
},
{
"name": "ValueC",
"someProperty": "SomeValue"
}
],
"someThing": [
{
"name": "ThingB",
"anotherProperty": "SomeValue"
},
{
"name": "ThingA",
" anotherProperty": "SomeValue "
}
]
}
I found code like this, but it sorts at top level, not itemsToSort
var jObj = (JObject)JsonConvert.DeserializeObject(json);
var props = jObj.Properties().ToList();
foreach (var prop in props)
{
prop.Remove();
}
foreach (var prop in props.OrderBy(p => p.Name))
{
jObj.Add(prop);
}
string result = jObj.ToString(Formatting.Indented);
How can I sort only the itemsToSort element?
Upvotes: 1
Views: 713
Reputation: 4261
If you want to sort only items inside itemsToSort
array, you could do the following:
var jObj = (JObject)JsonConvert.DeserializeObject(json);
var itemsToSort = jObj.Property("itemsToSort");
var vals = itemsToSort.Values()
.OfType<JObject>()
.OrderBy(x => x.Property("name").Value.ToString())
.ToList();
itemsToSort.Value = JContainer.FromObject(vals);
string result1 = jObj.ToString(Formatting.Indented);
It will take property itemsToSort
from deserialized object, take it values and sort by the string representation of name
property. To use it, you should be sure that deserialized object has the required property (itemsToSort
), it is array and every item of it has the property name
.
Actually, it is very simple and hardcoded solution. If you want to sort every item of array by specific key, you can use the following:
public string SortInnerArrays(JObject jObj, string innerKey)
{
foreach (var prop in jObj.Properties())
{
if (prop.Value.Type == JTokenType.Array)
{
var vals = prop.Values()
.OfType<JObject>()
.OrderBy(x => x.Property(innerKey).Value.ToString())
.ToList();
prop.Value = JContainer.FromObject(vals);
}
}
return jObj.ToString(Formatting.Indented);
}
and usage
var jObj = (JObject)JsonConvert.DeserializeObject(json);
string result1 = SortInnerArrays(jObj, "name");
And this is not an ideal solution, but looks much prettier. If you will want to sort arrays inside array inside root object, you will have to add some recursion for it. In my opinion, you should have a model class to store it's values, and sort it without converting to JObject
and passing the name of the field, simply:
var obj = JsonConvert.Deserialize<MyClass>(json);
obj.ItemsToSort = obj.ItemsToSort.OrderBy(x => x.Name).ToList();
var result = JsonConvert.SerializeObject(obj, Formatting.Indented);
Upvotes: 1