David Schwartz 426 Posted July 18, 2021 (edited) I'm dealing with an API that returns its data in a big JSON object that can vary from one request to another because the data being returned is somewhat dynamic. (Some is always there, and some is not.) It's structured generally like this: { section1: {...}, section2: {...}, section4: {...}, section7: {...}, . . . } Some sections consist of sub-objects (ie, {name : {...}} things) and some consist of array of JSON objects (ie, { name : [ ... ] } things) where the members are also JSON objects. Most examples I've seen approach this from the perspective that you know exactly what all of the 'name' values are for each object. In this case, I know there are a bunch of sections and sub-sections, but I don't necessarily know what all of the 'name' parts are. Also, you can infer from the above that there are sections 3, 5, and 6 that are not present in the results of this particular request. A section might not be there until you see it show up sometime; then it's like, "Oh, look at that ... something I haven't see before!" That is, it's not like the server in this case always returns, say, 15 sections, whether some are empty or not. Also, the sections may not always show up in the same order. What's the best way to parse this sort of thing? Part of what I'm not clear about is that I can ask for a Count on the number of things in an Array then iterate over the array, but what about the parts of a list -- like the sections named above? In my mind, I'd approach it using a Case statement, where I'd iterate through the list and drop each section name into the Case. If there's a match, then it would processed. An Else clause would handle any that aren't known yet, mostly for documentation purposes. (I'm ignoring the fact that Pascal's Case statements are still stuck in the 1970's and don't accept strings like most other contemporary languages today...) I'm working with Delphi's built-in JSON Objects Framework, although I could be persuated to use something else if it's noticeably simpler. None of the examples in the docwiki make much sense because they assume you already know the structure and names of everything being sent, as well as the order in some cases. What I *DO* know is the section names of particular interest, and within those sections there are specific elements I know by name that I want to extract the values from. Some of them are in secton sub-objects and some are in arrays of objects in a section. I also know which of these sections contain an array of objects and which are just sub-objects. Or said another way, I know that section values either look like a record or class (as opposed to a single-element array), or they're an array of records or classes. Edited July 18, 2021 by David Schwartz Share this post Link to post
stijnsanders 35 Posted July 18, 2021 If you're willing to examine an alternative, and if you're struggling with other JSON solutions that appear to 'bind' the JSON data to some sort of schema that determine the full extent of what you'd possibly do with the date, check out this JSON unit I've created in the margin of an attempt at a no-frills MongoDB connector: https://github.com/stijnsanders/jsonDoc#jsondoc I also dislike solutions that depend long lists of overloads for all kinds of types, so it depends on Variants heavily, especially that a Variant value can hold a reference to the interface of a live instance if anything, such as another IJSONDocument object. Also arrays in JSON are converted to and from Variant arrays. So using VarType, you could detect when data is an array or not, if it's an sub-object, you'll get varUnknown, look at the function JSON declared in the unit how to get a IJSONDocument reference. Also have a look at function JSONEnum to list the "sectionX" fields the base object might have. Share this post Link to post
Fr0sT.Brutal 900 Posted July 19, 2021 Hmm, I can't realize what puzzles you. Anyway you start from TJSONObject . Then grab its values one by one and check whether they're TJSONObject , TJSONArray or something else (using "is" operator). 1 Share this post Link to post
Guest Posted July 21, 2021 { "myArray": [10, 20, 30, 40], "myObject":{"subValue":44}, "version":"1.2" } { "myArray": [10, 20, 30, 40], "myObject":{"subValue":43, "subName":"AHA!"} } If "version" is missing, it's null. If "subName" is missing it's null. Or to express it differently any conceivable value not specified is null. It's actually like objects in JavaScript, you can almost "add anything to them anywhere". Or like this; If a JSON does not have a schema, then you can definitely miss "stuff" if you "analyse" it. So JSON requires documentation or a kind of "schema" IMHO, at least in your use case. HTH, correct me if needed. Share this post Link to post