What's the right way to handle JSON in iOS apps now? (Xojo 2020r2 and beyond)

With the Xojo framework being deemphasized in favor of API 2.0, what’s currently the best way to handle parsing JSON for the iOS target and in general?

It seems JSONItem still doesn’t work, but I don’t want to put a lot of effort towards using Xojo.Data’s GenerateJSON and ParseJSON methods as I’m guessing they’ll soon be deprecate much like Xojo.Core.Dictionary was…

Is the recommended practice to handle everything using the Dictionary class and the new GenerateJSON and ParseJSON methods in API 2.0?

@Christian_Schmitz - does the JSONMBS class in the “The MBS Xojo Util Plugin” work for iOS builds?

That’s what I’d use, GenerateJSON and ParseJSON.

2 Likes

Thanks @Kem_Tekinay - I figured this might be the case.

I think you have your own JSON classes too? Are you deemphasizing those now because Xojo’s parsing is working better?

if I recall, the old JSONItem class’ parsing was pretty slow; has performance improved with the two new API 2.0 methods?

JSONItem performance is unaffected right now, so my class is still relevant. I suspect this won’t be the case forever though, but still, if I were starting with JSON today, I’d dispense with JSONItem and use ParseJSON and GenerateJSON directly in all cases.

2 Likes

Thanks Kem! :smiley:

I realize I didn’t answer your performance question. Yes, the API methods are significantly faster than JSONItem or my JSONItem_MTC class, which is another reason I’d choose them.

1 Like

The better performance of the API 2.0 methods was inferred, but thank you for taking the time to explicitly confirm it!

2 Likes

Yes, works.

Thanks for confirming Christian.

Do you have any sense of how the performance of the JSONMBS compares to the GenerateJSON and ParseJSON methods in API 2.0?

How big may your JSON data be?

Speedwise, I expect GenerateJSON and ParseJSON be faster than anything a plugin could do, as the framework internally can access arrays and dictionaries faster.

But it may not be much difference.

@Kem_Tekinay It’s less about any result being particularly massive and more about potentially having to process “chunky-ish” (1000-15000 values which may have arrays in each of them) results multiple times in relatively quick succession. Parsing multiple, sets of results returned from an API.

@Christian_Schmitz Is your plugin able to utilize multiple cores? As explained above, I’m not parsing one result with a million rows. I’m needing to parse “tens of sets of data” returned in quick succession. (out of order processing is OK)

Thanks to both of you for your thoughtful questions and advice!

Currently JSONMBS class doesn’t do multithreading, but if needed, we could provide that. Even some asynchronous processing if desired.

Here’s something you can use to benchmark. You can figure out what some of the calls do:

#if not DebugBuild
  #pragma BackgroundTasks False
  #pragma NilObjectChecking False
  #pragma StackOverflowChecking False
  #pragma BoundsChecking False
#endif

const kCount as integer = 5000

var arr() as variant
arr.ResizeTo kCount - 1

var embedded() as variant = MakeArray( kCount - 1 )

for i as integer = 0 to arr.LastIndex
  arr( i ) = embedded
next

dim msg as string
dim sw as new Stopwatch_MTC
sw.Start

var j as string = GenerateJSON( arr )

sw.Stop
msg = "Generate: " + format( sw.ElapsedMicroseconds, "#," ) + " microsecs"
AddToResult msg

sw.Reset
sw.Start

call ParseJSON( j )

sw.Stop
msg = "Parse: " + format( sw.ElapsedMicroseconds, "#," ) + " microsecs"
AddToResult msg

AddToResult j.Bytes.ToString( "#,##0" )

(The embedded array is just the indexes, e.g., [1, 2, 3 … 4999].)

My results:

Generate: 6,591,910 microsecs
Parse: 5,372,441 microsecs
119,460,001
1 Like

For comparison, this JavaScript code:

var arr = Array(5000)
var embedded = Array(arr.length)

for (i = 0 ; i < arr.length ; i++) {
  embedded[i] = i
}

for (i = 0 ; i < arr.length ; i++) {
  arr[i] = embedded
}

var startMs
startMs = Date.now()
var s = JSON.stringify(arr)
console.log('Generate: ' + (Date.now() - startMs))

startMs = Date.now()
var j = JSON.parse(s)
console.log('Parse: ' + (Date.now() - startMs))

console.log(j.length)
console.log(s.length)

The results:

Generate: 1044
Parse: 663
5000
119460001

JavaScript is not my forte though, so I hope someone will say “that doesn’t do the same thing, you dope.”

1 Like

I’m currently updating an app I wrote last year to API2.0. I was already using ParseJSON from the old API. I found out that the new version uses Variant instead of Auto so it required some code modification to access the data without “Suddenly…BLAM!” happening.

You can try JavaScriptEngineMBS class to have a JavaScript engine within Xojo.
And it can of course work with JSON. And you can run functions multithreaded.

1 Like