✅ Newtonsoft JSON and unknown data
Say I have an Input set which looks like this:
Array of Unknown Json Objects
as request body to my API
How am I going to count the amount of unique properties in all the Json Objects within the Array that the request body contains?
And how am I going to count the occurrences of each of those unique properties within the entire array of json objects?
I'm hoping I can do this with Newtonsoft.Json with as little "dynamic" data as possible, but I am aware that since it's unknown what kind of data is passed into the API I am going to have to generalize a lot.
Any ideas?34 Replies
Parse the various JsonValue etc and keep a count. Good luck
Dictionary<string, object>
Okay so I have this:
so in my Api Methods I just go:
I'm not entirely sure how I can parse this
Something like this?
I think I have something now but it returns a count of 1 each time, and with the data I provide I'm sure the count should be 4 (except for a single prop that should be 1)
Can't do this with Newtonsoft.Json though?
I think in JObject you get KeyValuePair<string, string> if you iterate over it..
But I'll see if I can use your example and edit slightly for my usage.
That is newtonsoft. JObjects are complicated and too much work (and still not strongly typed), when json already perfectly matches Dictionary<string,object> format
Also worth adding is that if you do know some of the properties, you can make the model with those, and there's a newtonsoft attribute to dump any properties not in your model, into a Dictionary<string,object> on the model
but the input will always be of type
string[]
(I checked the requirements for the API, it has to be.a string[] deserialized from json would have just one key then
the string would look something like this:
so I can parse that as a JObject
right, but the value could possibly itself be an array, or a nested dictionary object
You could probably parse it into a List<JObject> and check them individually like that, the dictionaries are just kind of easier
The value of "data" is an array of the string objects I just exampled, these can contain their own arrays or nested objects yea
Oh, and I see a flaw in my explanation already too... feck...
Also I find it hard to believe that your API doesn't tell you what properties to expect
Not that I don't believe you just that they really should have a better way to send those than as unidentified properties
if they even have an example json that contains all possible ones, there's this
I forgot to add that I have to return a count for each of the properties
so for example I have these input strings:
like 600 times this object with different "values" for each of the items.
What I want is a return body that looks like this:
and if any of the objects have another property in them that does not exist in the rest, it's just added to this results array with its own count
Yeah that's a lot easier if you can just build the models
Like that's just a list of
I can't because the json objects can litteraly contain anything.
Basically the use-case would be:
User has a database full of data, grabs one of their tables and converts each row into a json object. Then calls my API to count the number of occurrences of each column in the dataset. So the user grabs an array of JSON objects from the database (convert row into object, or use document based database)
and sends it off.
My API has to tell the amount of occurrences in that dataset without knowing (or caring) what property names and values are in there.
The example I gave is just that, and example. But the properties and their values can be anything
so no, I can't create a model ahead of time 😅 so I need to be able to count this without caring about the model
Then sure, dictionary or jobject or whatever. Sounds like you're only interested in properties that are nested in the top level objects so it doesn't have to be that recursive
Yea I do need to be that recursive, I needed to give an example that was easy to setup, I'll grab some deeper nested examples later. I just needed to have an initial starting point first
then yeah just, as above. Your input, being valid json, will have to look like
So you can at least, knowing that, parse it into a List<Dictionary<string,object>> or List<JObject>
Though that's a bit less generic so maybe just do it as above. The initial dictionary will just have one key and one value (the array), and the nested stuff gets recursed
and then probably have another Dictionary<string,int> to store the counts
Okay, but how do I parse a string into a Dictionary<string, object>?
deserialize as normal to that type
I get a feeling this method will return a total count of the entire object, instead of a count for a property.
So count = 20.000
instead of "name" count = 600
but I'll give this a shot, and see if this works out
I would say that's up to you to rework but I was already reworking it
Sorry for interrupting 😅
Though tbh JObject could be cleaner. I just never worked with them and the dictionaries make more sense to me (and I don't have to look it up when I'm writing freehand code in discord 😛 ). Either way
I think doing a
foreach
over a JObject also turns into a KeyValuePair<T,P>
Let me see if I can translate this 😅Basically it iterates over the main dictionary, incrementing something like
countedProps["Name"]
when it sees a property with key "Name". Then if the value contains properties (a dictionary) or is a list containing properties, run the method on the inner thing, and add its results into countedProps
But, this doesn't catch all cases; if there is an array containing arrays of objects with keys on them, it wouldn't get to those, for example
Unfortunately I've done this before... lollol yea 😅 I am starting to get the "unfortunately" part lol
Very very similar goal actually, in my case I wanted to take lots of unknown properties and flatten them so that I can output a single 'row', with each column being a property (or an inner-object's property)
I've got a meeting to dive into that will last me another 3 hours, after which I'll check again if I can come up with something lol
yea it's almost the same..
Mine needs to basically return an array of simple objects
but I'll be back later, thanks for the patience!
It's a lot easier with JObjects actually
D.Mentia#0614
REPL Result: Success
Console Output
Compile: 673.815ms | Execution: 150.629ms | React with ❌ to remove this embed.
Hey man, sorry I eventually returned home by 11pm, so I didn't get back to it.
I'm back on it now, and your method seems solid, I'm just trying to figure out how to translate
string[]
into JObject 😅
Because I'm passing the class RequestBody
into my initial JsonConvert.DeserializeObject<RequestBody>(req.Body);
Which looks like this:
Which technically I should be able to convert string[]
into JObject
] but then I get this error saying
So I tried just transforming each item of the string[]
into its own JObject (which is possible) but then I get numerous amounts of seperate Dictionaries instead of a single one.
So what I also tried was Dictionary<string, int> countedProperties = CountNested(request.Data);
but then I get the following error:
so I'm a little confused 😅
Ooh, I think I got it!
So here's my initial input from the user:
and here's the initial input at the API:
And the CountNested method you wrote, but I turned it into an extension
as well as the IncrementCount method:
And then the result: (After repeating it 4 times with a single object containing a unique property)
I'll leave the ticket open until you see my thank you here 😅 you've been an amazing patient one to help me, so thank you very much!!
Oh, and some nested data:
results in:
so, awesome!Was this issue resolved? If so, run
/close
- otherwise I will mark this as stale and this post will be archived until there is new activity.