Adam
Adam

Reputation: 33146

Convert NSString to NSDictionary and NSDictionary to NSString

There are many questions on this already, but the answers given are situation-specific, answering the poster's personal problem rather than the question title.

I would like to know if there is a general, universal, easy way to convert an NSString to an NSDictionary, and vice versa?

I've got difficult/complex/non-cross-platform approaches, but surely there must be an easier way?

Here's what I know / have tested:

  1. Apple provides a Dictionary -> String method that has no inverse, and works perfectly so long as your Dictionary is only basic datatypes, arrays, and dictionaries. This covers most real-world cases, but Apple doesn't give an inverse :(.
    1. [myDictionary description];
    2. // no way back ? Why not?
  2. Apple has an intermediate approach using NSData that fails silently, so that it only works in a LIMITED set of real-world cases:
    1. [myString dataUsingEncoding:NSUTF8StringEncoding];
    2. [[NSString alloc] initWithData:myData encoding:NSUTF8StringEncoding]; // NB: silently fails in many cases, returns nil string
  3. Apple has MULTIPLE, INCOMPATIBLE ways of converting NSDictionary -> NSData -> NSDicitonary that work well - but they are using NSData, so they are not a straight conversion, and they are harder to work with
    1. KeyedArchiver:
      1. [NSKeyedArchiver archivedDataWithRootObject:myDictionary];
      2. [NSKeyedUnarchiver unarchiveObjectWithData:myData];
    2. PropertyListSerialization:
      1. [NSPropertyListSerialization dataFromPropertyList:plist format:NSPropertyListXMLFormat_v1_0 errorDescription:&error];
      2. [NSPropertyListSerialization propertyListFromData:plistData mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&error];
    3. NSJSONSerialization:
      1. [NSJSONSerialization JSONObjectWithData:myData options:0 error:nil];
      2. [dataWithJSONObject:myDictionary options:0 error:nil];

As it stands, the only route that is GUARANTEED to work appears to be:

Write lots of code to output a verbose XML or JSON, converting it to NSData, then converting back into NSString, and send that on the wire.

Anything else has a slightly-less-than-100% success rate. Unfortunately, this technique turns a very common problem (string -> dictionary -> string) into a multiline chunk of silly boilerplate code we shouldn't be writing.

Also ... the XML-or-JSON approach is the only one that correctly reports failures (if they occur) - both the encoding systems take NSError pointers.

Upvotes: 5

Views: 11344

Answers (2)

user529758
user529758

Reputation:

Apple provides a Dictionary -> String method that has no inverse

Huh? False. And no, you are not supposed to rely on description. Use property lists instead.

Forwards:

NSData *plist = [NSPropertyListSerialization
    dataWithPropertyList:theDict
                  format:NSPropertyListXMLFormat_v1_0
                 options:kNilOptions
                   error:NULL];

NSString *str = [[NSString alloc] initWithData:plist encoding:NSUTF8StringEncoding];

Backwards:

NSDictionary *dict = [NSPropertyListSerialization
    propertyListWithData:[str dataUsingEncoding:NSUTF8StringEncoding]
                 options:kNilOptions
                  format:NULL
                   error:NULL];

Sidenote:

and works perfectly so long as your Dictionary is only basic datatypes

those are called "property list objects".

Upvotes: 10

Nicolas Manzini
Nicolas Manzini

Reputation: 8546

What you want is:

id<nscoding> obj;

NSData * data     = [NSKeyedArchiver archivedDataWithRootObject:obj];
NSString * string = [data base64EncodedString];

And then the other way around

NSString * string;

NSData * data    = [NSData dataFromBase64String:string];
id<nscoding> obj = [NSKeyedUnarchiver unarchiveObjectWithData:data]

You can add base64EncodedString and dataFromBase64String: with the NSData category available here NSData+Base64

NSUTF8StringEncoding return nil when you try to encode something that is not data made of an utf8 string.

Upvotes: 2

Related Questions