Sorting JObject inside array by a field value
I have a JSON string like below:
"MetaData":
"ResourcesUsed": 1
,
"Result": [
"locations": [
"country": "Papua New Guinea",
"city": "Jacquinot Bay",
"locTypeAttributes":
"localDate": "2018-10-08T04:21:00-07:00",
"utcDate": "2018-10-08T04:21:00-07:00",
,
"point":
"coordinates": [
151.52,
-5.6
],
"type": "Point"
,
"country": "Papua New Guinea2",
"city": "Jacquinot Bay2",
"locTypeAttributes":
"localDate": "2018-10-08T04:21:00-07:00",
"utcDate": "2018-10-02T04:21:00-07:00",
,
"point":
"coordinates": [
151.52,
-5.6
],
"type": "Point"
]
]
I converted it to a JSON object using Newtonsoft. What I want to do is to sort the locations
array(s) inside the Result
array by the utcDate
field nested in each locations
item. I found the following thread: C# Sort JSON string keys. However, I could not still implement it since I have arrays inside my object, while that question deals purely with sorting objects inside objects alphabetically by property name.
Here is a piece of code that I wrote so far:
public string GenerateJson()
var model = (JObject)JsonConvert.DeserializeObject(data);
Sort(model);
private void Sort(JObject jObj)
var props = jObj["Result"][0]["locations"].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]);
c# json sorting json.net
add a comment |
I have a JSON string like below:
"MetaData":
"ResourcesUsed": 1
,
"Result": [
"locations": [
"country": "Papua New Guinea",
"city": "Jacquinot Bay",
"locTypeAttributes":
"localDate": "2018-10-08T04:21:00-07:00",
"utcDate": "2018-10-08T04:21:00-07:00",
,
"point":
"coordinates": [
151.52,
-5.6
],
"type": "Point"
,
"country": "Papua New Guinea2",
"city": "Jacquinot Bay2",
"locTypeAttributes":
"localDate": "2018-10-08T04:21:00-07:00",
"utcDate": "2018-10-02T04:21:00-07:00",
,
"point":
"coordinates": [
151.52,
-5.6
],
"type": "Point"
]
]
I converted it to a JSON object using Newtonsoft. What I want to do is to sort the locations
array(s) inside the Result
array by the utcDate
field nested in each locations
item. I found the following thread: C# Sort JSON string keys. However, I could not still implement it since I have arrays inside my object, while that question deals purely with sorting objects inside objects alphabetically by property name.
Here is a piece of code that I wrote so far:
public string GenerateJson()
var model = (JObject)JsonConvert.DeserializeObject(data);
Sort(model);
private void Sort(JObject jObj)
var props = jObj["Result"][0]["locations"].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]);
c# json sorting json.net
Why not deserialize to a custom class and then sort it (normally)
– Make StackOverflow Good Again
Nov 15 '18 at 20:05
@Disaffected1070452 that's my last resort, I was trying to avoid creating any custom class.
– DeadlyDagger
Nov 15 '18 at 20:08
Do you want to sort the"Result":
array, or do you want to sort each"Result[*].locations"
array? Because the locations themselves are an array so there might in principle be more than one, each with its ownutcDate
. And if you do want to sort the"Results"
array how do you want to deal with the situation where a result has multiple locations with multipleutcDate
values? C# Sort JSON string keys is for recursively sorting a tree of objects by property name so it doesn't really apply here.
– dbc
Nov 15 '18 at 20:38
@dbc I just simplified the JSON string, so in Result, we will always have one array of locations, I want to sort that array byutcDate
.
– DeadlyDagger
Nov 15 '18 at 21:19
add a comment |
I have a JSON string like below:
"MetaData":
"ResourcesUsed": 1
,
"Result": [
"locations": [
"country": "Papua New Guinea",
"city": "Jacquinot Bay",
"locTypeAttributes":
"localDate": "2018-10-08T04:21:00-07:00",
"utcDate": "2018-10-08T04:21:00-07:00",
,
"point":
"coordinates": [
151.52,
-5.6
],
"type": "Point"
,
"country": "Papua New Guinea2",
"city": "Jacquinot Bay2",
"locTypeAttributes":
"localDate": "2018-10-08T04:21:00-07:00",
"utcDate": "2018-10-02T04:21:00-07:00",
,
"point":
"coordinates": [
151.52,
-5.6
],
"type": "Point"
]
]
I converted it to a JSON object using Newtonsoft. What I want to do is to sort the locations
array(s) inside the Result
array by the utcDate
field nested in each locations
item. I found the following thread: C# Sort JSON string keys. However, I could not still implement it since I have arrays inside my object, while that question deals purely with sorting objects inside objects alphabetically by property name.
Here is a piece of code that I wrote so far:
public string GenerateJson()
var model = (JObject)JsonConvert.DeserializeObject(data);
Sort(model);
private void Sort(JObject jObj)
var props = jObj["Result"][0]["locations"].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]);
c# json sorting json.net
I have a JSON string like below:
"MetaData":
"ResourcesUsed": 1
,
"Result": [
"locations": [
"country": "Papua New Guinea",
"city": "Jacquinot Bay",
"locTypeAttributes":
"localDate": "2018-10-08T04:21:00-07:00",
"utcDate": "2018-10-08T04:21:00-07:00",
,
"point":
"coordinates": [
151.52,
-5.6
],
"type": "Point"
,
"country": "Papua New Guinea2",
"city": "Jacquinot Bay2",
"locTypeAttributes":
"localDate": "2018-10-08T04:21:00-07:00",
"utcDate": "2018-10-02T04:21:00-07:00",
,
"point":
"coordinates": [
151.52,
-5.6
],
"type": "Point"
]
]
I converted it to a JSON object using Newtonsoft. What I want to do is to sort the locations
array(s) inside the Result
array by the utcDate
field nested in each locations
item. I found the following thread: C# Sort JSON string keys. However, I could not still implement it since I have arrays inside my object, while that question deals purely with sorting objects inside objects alphabetically by property name.
Here is a piece of code that I wrote so far:
public string GenerateJson()
var model = (JObject)JsonConvert.DeserializeObject(data);
Sort(model);
private void Sort(JObject jObj)
var props = jObj["Result"][0]["locations"].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]);
c# json sorting json.net
c# json sorting json.net
edited Nov 15 '18 at 22:44
dbc
55.4k875130
55.4k875130
asked Nov 15 '18 at 19:29
DeadlyDaggerDeadlyDagger
255
255
Why not deserialize to a custom class and then sort it (normally)
– Make StackOverflow Good Again
Nov 15 '18 at 20:05
@Disaffected1070452 that's my last resort, I was trying to avoid creating any custom class.
– DeadlyDagger
Nov 15 '18 at 20:08
Do you want to sort the"Result":
array, or do you want to sort each"Result[*].locations"
array? Because the locations themselves are an array so there might in principle be more than one, each with its ownutcDate
. And if you do want to sort the"Results"
array how do you want to deal with the situation where a result has multiple locations with multipleutcDate
values? C# Sort JSON string keys is for recursively sorting a tree of objects by property name so it doesn't really apply here.
– dbc
Nov 15 '18 at 20:38
@dbc I just simplified the JSON string, so in Result, we will always have one array of locations, I want to sort that array byutcDate
.
– DeadlyDagger
Nov 15 '18 at 21:19
add a comment |
Why not deserialize to a custom class and then sort it (normally)
– Make StackOverflow Good Again
Nov 15 '18 at 20:05
@Disaffected1070452 that's my last resort, I was trying to avoid creating any custom class.
– DeadlyDagger
Nov 15 '18 at 20:08
Do you want to sort the"Result":
array, or do you want to sort each"Result[*].locations"
array? Because the locations themselves are an array so there might in principle be more than one, each with its ownutcDate
. And if you do want to sort the"Results"
array how do you want to deal with the situation where a result has multiple locations with multipleutcDate
values? C# Sort JSON string keys is for recursively sorting a tree of objects by property name so it doesn't really apply here.
– dbc
Nov 15 '18 at 20:38
@dbc I just simplified the JSON string, so in Result, we will always have one array of locations, I want to sort that array byutcDate
.
– DeadlyDagger
Nov 15 '18 at 21:19
Why not deserialize to a custom class and then sort it (normally)
– Make StackOverflow Good Again
Nov 15 '18 at 20:05
Why not deserialize to a custom class and then sort it (normally)
– Make StackOverflow Good Again
Nov 15 '18 at 20:05
@Disaffected1070452 that's my last resort, I was trying to avoid creating any custom class.
– DeadlyDagger
Nov 15 '18 at 20:08
@Disaffected1070452 that's my last resort, I was trying to avoid creating any custom class.
– DeadlyDagger
Nov 15 '18 at 20:08
Do you want to sort the
"Result":
array, or do you want to sort each "Result[*].locations"
array? Because the locations themselves are an array so there might in principle be more than one, each with its own utcDate
. And if you do want to sort the "Results"
array how do you want to deal with the situation where a result has multiple locations with multiple utcDate
values? C# Sort JSON string keys is for recursively sorting a tree of objects by property name so it doesn't really apply here.– dbc
Nov 15 '18 at 20:38
Do you want to sort the
"Result":
array, or do you want to sort each "Result[*].locations"
array? Because the locations themselves are an array so there might in principle be more than one, each with its own utcDate
. And if you do want to sort the "Results"
array how do you want to deal with the situation where a result has multiple locations with multiple utcDate
values? C# Sort JSON string keys is for recursively sorting a tree of objects by property name so it doesn't really apply here.– dbc
Nov 15 '18 at 20:38
@dbc I just simplified the JSON string, so in Result, we will always have one array of locations, I want to sort that array by
utcDate
.– DeadlyDagger
Nov 15 '18 at 21:19
@dbc I just simplified the JSON string, so in Result, we will always have one array of locations, I want to sort that array by
utcDate
.– DeadlyDagger
Nov 15 '18 at 21:19
add a comment |
1 Answer
1
active
oldest
votes
You can sort each individual "Result[*].locations"
array using LINQ as follows:
// Load the JSON without parsing or converting any dates.
var model = JsonConvert.DeserializeObject<JObject>(data, new JsonSerializerSettings DateParseHandling = DateParseHandling.None );
// Construct a serializer that converts all DateTime values to UTC
var serializer = JsonSerializer.CreateDefault(new JsonSerializerSettings DateTimeZoneHandling = DateTimeZoneHandling.Utc );
foreach (var locations in model.SelectTokens("Result[*].locations").OfType<JArray>())
// Then sort the locations by utcDate converting the value to UTC at this time.
var query = from location in locations
let utcDate = location.SelectToken("locTypeAttributes.utcDate").ToObject<DateTime>(serializer)
orderby utcDate
select location;
locations.ReplaceAll(query.ToList());
Notes:
The JSON is initially loaded using
DateParseHandling.None
to prevent the"localDate"
and"utcDate"
strings from being prematurely interpreted asDateTime
objects with a uniformDateTime.Kind
.(For a discussion of how Json.NET interprets strings that look like dates, see Serializing Dates in JSON.)
We then iterate through all
"locations"
arrays usingSelectTokens("Result[*].locations")
where[*]
is the JSONPath wildcard character, selecting all entries in the"Results"
array.We then order each
"locations"
array by deserializing the nestedlocTypeAttributes.utcDate
to a UTC date, then ordering using LINQ.Finally the array is updated using
JArray.ReplaceAll()
.If any
locTypeAttributes.utcDate
property is missing, an exception will be thrown. You could instead deserialize toDateTime?
if that is a possibility.
Working sample .Net fiddle here.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53326681%2fsorting-jobject-inside-array-by-a-field-value%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
You can sort each individual "Result[*].locations"
array using LINQ as follows:
// Load the JSON without parsing or converting any dates.
var model = JsonConvert.DeserializeObject<JObject>(data, new JsonSerializerSettings DateParseHandling = DateParseHandling.None );
// Construct a serializer that converts all DateTime values to UTC
var serializer = JsonSerializer.CreateDefault(new JsonSerializerSettings DateTimeZoneHandling = DateTimeZoneHandling.Utc );
foreach (var locations in model.SelectTokens("Result[*].locations").OfType<JArray>())
// Then sort the locations by utcDate converting the value to UTC at this time.
var query = from location in locations
let utcDate = location.SelectToken("locTypeAttributes.utcDate").ToObject<DateTime>(serializer)
orderby utcDate
select location;
locations.ReplaceAll(query.ToList());
Notes:
The JSON is initially loaded using
DateParseHandling.None
to prevent the"localDate"
and"utcDate"
strings from being prematurely interpreted asDateTime
objects with a uniformDateTime.Kind
.(For a discussion of how Json.NET interprets strings that look like dates, see Serializing Dates in JSON.)
We then iterate through all
"locations"
arrays usingSelectTokens("Result[*].locations")
where[*]
is the JSONPath wildcard character, selecting all entries in the"Results"
array.We then order each
"locations"
array by deserializing the nestedlocTypeAttributes.utcDate
to a UTC date, then ordering using LINQ.Finally the array is updated using
JArray.ReplaceAll()
.If any
locTypeAttributes.utcDate
property is missing, an exception will be thrown. You could instead deserialize toDateTime?
if that is a possibility.
Working sample .Net fiddle here.
add a comment |
You can sort each individual "Result[*].locations"
array using LINQ as follows:
// Load the JSON without parsing or converting any dates.
var model = JsonConvert.DeserializeObject<JObject>(data, new JsonSerializerSettings DateParseHandling = DateParseHandling.None );
// Construct a serializer that converts all DateTime values to UTC
var serializer = JsonSerializer.CreateDefault(new JsonSerializerSettings DateTimeZoneHandling = DateTimeZoneHandling.Utc );
foreach (var locations in model.SelectTokens("Result[*].locations").OfType<JArray>())
// Then sort the locations by utcDate converting the value to UTC at this time.
var query = from location in locations
let utcDate = location.SelectToken("locTypeAttributes.utcDate").ToObject<DateTime>(serializer)
orderby utcDate
select location;
locations.ReplaceAll(query.ToList());
Notes:
The JSON is initially loaded using
DateParseHandling.None
to prevent the"localDate"
and"utcDate"
strings from being prematurely interpreted asDateTime
objects with a uniformDateTime.Kind
.(For a discussion of how Json.NET interprets strings that look like dates, see Serializing Dates in JSON.)
We then iterate through all
"locations"
arrays usingSelectTokens("Result[*].locations")
where[*]
is the JSONPath wildcard character, selecting all entries in the"Results"
array.We then order each
"locations"
array by deserializing the nestedlocTypeAttributes.utcDate
to a UTC date, then ordering using LINQ.Finally the array is updated using
JArray.ReplaceAll()
.If any
locTypeAttributes.utcDate
property is missing, an exception will be thrown. You could instead deserialize toDateTime?
if that is a possibility.
Working sample .Net fiddle here.
add a comment |
You can sort each individual "Result[*].locations"
array using LINQ as follows:
// Load the JSON without parsing or converting any dates.
var model = JsonConvert.DeserializeObject<JObject>(data, new JsonSerializerSettings DateParseHandling = DateParseHandling.None );
// Construct a serializer that converts all DateTime values to UTC
var serializer = JsonSerializer.CreateDefault(new JsonSerializerSettings DateTimeZoneHandling = DateTimeZoneHandling.Utc );
foreach (var locations in model.SelectTokens("Result[*].locations").OfType<JArray>())
// Then sort the locations by utcDate converting the value to UTC at this time.
var query = from location in locations
let utcDate = location.SelectToken("locTypeAttributes.utcDate").ToObject<DateTime>(serializer)
orderby utcDate
select location;
locations.ReplaceAll(query.ToList());
Notes:
The JSON is initially loaded using
DateParseHandling.None
to prevent the"localDate"
and"utcDate"
strings from being prematurely interpreted asDateTime
objects with a uniformDateTime.Kind
.(For a discussion of how Json.NET interprets strings that look like dates, see Serializing Dates in JSON.)
We then iterate through all
"locations"
arrays usingSelectTokens("Result[*].locations")
where[*]
is the JSONPath wildcard character, selecting all entries in the"Results"
array.We then order each
"locations"
array by deserializing the nestedlocTypeAttributes.utcDate
to a UTC date, then ordering using LINQ.Finally the array is updated using
JArray.ReplaceAll()
.If any
locTypeAttributes.utcDate
property is missing, an exception will be thrown. You could instead deserialize toDateTime?
if that is a possibility.
Working sample .Net fiddle here.
You can sort each individual "Result[*].locations"
array using LINQ as follows:
// Load the JSON without parsing or converting any dates.
var model = JsonConvert.DeserializeObject<JObject>(data, new JsonSerializerSettings DateParseHandling = DateParseHandling.None );
// Construct a serializer that converts all DateTime values to UTC
var serializer = JsonSerializer.CreateDefault(new JsonSerializerSettings DateTimeZoneHandling = DateTimeZoneHandling.Utc );
foreach (var locations in model.SelectTokens("Result[*].locations").OfType<JArray>())
// Then sort the locations by utcDate converting the value to UTC at this time.
var query = from location in locations
let utcDate = location.SelectToken("locTypeAttributes.utcDate").ToObject<DateTime>(serializer)
orderby utcDate
select location;
locations.ReplaceAll(query.ToList());
Notes:
The JSON is initially loaded using
DateParseHandling.None
to prevent the"localDate"
and"utcDate"
strings from being prematurely interpreted asDateTime
objects with a uniformDateTime.Kind
.(For a discussion of how Json.NET interprets strings that look like dates, see Serializing Dates in JSON.)
We then iterate through all
"locations"
arrays usingSelectTokens("Result[*].locations")
where[*]
is the JSONPath wildcard character, selecting all entries in the"Results"
array.We then order each
"locations"
array by deserializing the nestedlocTypeAttributes.utcDate
to a UTC date, then ordering using LINQ.Finally the array is updated using
JArray.ReplaceAll()
.If any
locTypeAttributes.utcDate
property is missing, an exception will be thrown. You could instead deserialize toDateTime?
if that is a possibility.
Working sample .Net fiddle here.
edited Nov 16 '18 at 0:44
answered Nov 15 '18 at 22:38
dbcdbc
55.4k875130
55.4k875130
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53326681%2fsorting-jobject-inside-array-by-a-field-value%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Why not deserialize to a custom class and then sort it (normally)
– Make StackOverflow Good Again
Nov 15 '18 at 20:05
@Disaffected1070452 that's my last resort, I was trying to avoid creating any custom class.
– DeadlyDagger
Nov 15 '18 at 20:08
Do you want to sort the
"Result":
array, or do you want to sort each"Result[*].locations"
array? Because the locations themselves are an array so there might in principle be more than one, each with its ownutcDate
. And if you do want to sort the"Results"
array how do you want to deal with the situation where a result has multiple locations with multipleutcDate
values? C# Sort JSON string keys is for recursively sorting a tree of objects by property name so it doesn't really apply here.– dbc
Nov 15 '18 at 20:38
@dbc I just simplified the JSON string, so in Result, we will always have one array of locations, I want to sort that array by
utcDate
.– DeadlyDagger
Nov 15 '18 at 21:19