NSJSONSerialization generating NSCFString* and NSTaggedPointerString*
Asked Answered
N

2

18

Executing NSJSONSerialization on the following json sometimes gives me NSCFString* and sometimes NSTaggedPointerString* on string values. Does anyone know why this is the case and what NSJSONSerialization uses to determine which type it returns?

jsonData = [NSJSONSerialization JSONObjectWithData:data
                                                   options:kNilOptions
                                                     error:&parseError];

    {
      "UserPermissionsService": {
        "ServiceHeader": {}, 
        "UserApplicationPermissions": {
          "ApplicationPermissions": {
            "ApplicationID": "TEST", 
            "Permission": [
              {
                "Locations": [
                  "00000"
                ], 
                "PermissionID": "LOGIN"
              }, 
              {
                "Locations": [
                  "00000"
                ], 
                "PermissionID": "SALES_REPORT_VIEW"
              }
            ]
          }
        }
      }
    }

"LOGIN" comes back as a NSTaggedPointerString*. "SALES_REPORT_VIEW" comes back is a NSCFString*. This is having an impact downstream where I'm using and casting the values.

UPDATE

Here's what I learned...

"NSTaggedPointerString results when the whole value can be kept in the pointer itself without allocating any data."

There's a detailed explanation here...

https://www.mikeash.com/pyblog/friday-qa-2015-07-31-tagged-pointer-strings.html

Since NSTaggedPointerString is a subclass of NSString showing quotes / not showing quotes should never been an issue for me as the data is used.

Thanks for everyone that commented. I'm comfortable I understand what NSJSONSerialization is doing.

Naval answered 13/10, 2015 at 14:47 Comment(7)
What are you doing that it makes a difference? You always get an NSString*. Which subclass of NSString* shouldn't ever matter to you.Manslaughter
Google for NSTaggedPointerString. If this makes a difference to you then you are doing something very, very wrong. Tagged pointers are very common on 64 bit systems for small values where the whole value can be kept in the pointer itself without allocating any data.Manslaughter
One example is that when show in the UI (written to a UITextField) the NSTaggedPointerString* doesn't have quotes around it while the NSString* does have quotes around it.Naval
@Justin Domnitz I don't believe you are on the right track here, please add an example of how you use the values or their types.Ass
I think we've gone a little off track here. :) I'm really just trying to understand the results I'm getting from NSJSONSerialization. The best answer seems to be from gnasher729 with regard to the system determining that "NSTaggedPointerString results when the whole value can be kept in the pointer itself without allocating any data". Can anyone point me to the documentation on this? Google is not yielding anything useful (which is why I posted the question here).Naval
Show us the code. This is how NSJSONSerialization works for thousands and thousands of applications, and you're the only one with the problem.Manslaughter
Lol @Manslaughter someone comes to stackoverflow with a question but receives more questions instead, great... Also, Justin if you found an answer please create one and mark yours as answered. For example, I have problems when NSJSONSerialization messes up dictionary keys as NSTaggedPointerStrings and can no longer access those values unless they are cast explicitly which makes for nasty looking indexingEuphorbiaceous
T
1

Much of Foundation is implemented as class clusters. TL;DR you interact with it as an NSString but foundation will change the backing implementation to optimize for certain performance or space characteristics based on the actual contents.

If you are curious one of the Foundation team dumped a list of the class clusters as of iOS 11 here

Tavia answered 9/1, 2018 at 14:35 Comment(0)
L
0

I FIXED IT BY USING "MUTABLECOPY"

I had the same issue. For some "performance" mechanism apparently apple uses NSTaggedPointerString for "well known" strings such as "California" but this might be an issue since for some weird reason the NSJSONSerialization doesn't add the quotes around this NSTaggedPointerString type of strings. The work around is simple:

NSString *taggedString = @"California";
[data setObject:[taggedString mutableCopy] forKey:@"state"]

Works like a charm.

Lyautey answered 27/3, 2019 at 2:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.