Generate JSON string from NSDictionary in iOS
Asked Answered
W

14

358

I have a dictionary I need to generate a JSON string by using dictionary. Is it possible to convert it? Can you guys please help on this?

Worsen answered 16/6, 2011 at 8:7 Comment(2)
@RicardoRivaldo that is thisGuardant
anybody coming here from google search, please read through the answer below by @GuillaumeNedranedrah
W
242

Here are categories for NSArray and NSDictionary to make this super-easy. I've added an option for pretty-print (newlines and tabs to make easier to read).

@interface NSDictionary (BVJSONString)
-(NSString*) bv_jsonStringWithPrettyPrint:(BOOL) prettyPrint;
@end

.

@implementation NSDictionary (BVJSONString)

  -(NSString*) bv_jsonStringWithPrettyPrint:(BOOL) prettyPrint {
     NSError *error;
     NSData *jsonData = [NSJSONSerialization dataWithJSONObject:self
                                                   options:(NSJSONWritingOptions)    (prettyPrint ? NSJSONWritingPrettyPrinted : 0)
                                                     error:&error];

     if (! jsonData) {
        NSLog(@"%s: error: %@", __func__, error.localizedDescription);
        return @"{}";
     } else {
        return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
     } 
 }
@end

.

@interface NSArray (BVJSONString)
- (NSString *)bv_jsonStringWithPrettyPrint:(BOOL)prettyPrint;
@end

.

@implementation NSArray (BVJSONString)
-(NSString*) bv_jsonStringWithPrettyPrint:(BOOL) prettyPrint {
    NSError *error;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:self
                                                       options:(NSJSONWritingOptions) (prettyPrint ? NSJSONWritingPrettyPrinted : 0)
                                                         error:&error];

    if (! jsonData) {
        NSLog(@"%s: error: %@", __func__, error.localizedDescription);
        return @"[]";
    } else {
        return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    }
}
@end
Walkyrie answered 28/11, 2013 at 9:30 Comment(4)
if we create a category of NSObject and put the same method, it works for both NSArray and NSDictionary. No need to write two separate files/interfaces. And it should return nil in case of error.Grannias
Why do you assume that NSUTF8StringEncoding is the correct encoding?Injudicious
Nevermind, the documentation says "The resulting data is a encoded in UTF-8."Injudicious
@AbdullahUmer That's what I've done too as I presume it'll also work on NSNumber, NSString, and NSNull – will find out in a minute or two!Philemol
B
775

Apple added a JSON parser and serializer in iOS 5.0 and Mac OS X 10.7. See NSJSONSerialization.

To generate a JSON string from a NSDictionary or NSArray, you do not need to import any third party framework anymore.

Here is how to do it:

NSError *error; 
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dictionaryOrArrayToOutput 
                                                   options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string
                                                     error:&error];

if (! jsonData) {
    NSLog(@"Got an error: %@", error);
} else {
    NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
}
Blastocoel answered 26/1, 2012 at 15:54 Comment(6)
This is good advice...it's really annoying to have projects have a ton of third party libraries.Diabolism
+1 Adding this as a category to NSArray and NSDictionary would make reusing it much simpler.Plasmo
how to convert the json back to dictionary?Conformable
@Conformable - [NSJSONSerialization JSONObjectWithData:options:error:] returns a Foundation objec from given JSON dataOcciput
Successfully converted to JSON format but I'm getting this error *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** +[NSJSONSerialization dataWithJSONObject:options:error:]: Invalid top-level type in JSON write' *** First throw call stack:Opalescent
This not make escape string for special characters like & (ampersand). for example: output is like & instead of \&Truda
W
242

Here are categories for NSArray and NSDictionary to make this super-easy. I've added an option for pretty-print (newlines and tabs to make easier to read).

@interface NSDictionary (BVJSONString)
-(NSString*) bv_jsonStringWithPrettyPrint:(BOOL) prettyPrint;
@end

.

@implementation NSDictionary (BVJSONString)

  -(NSString*) bv_jsonStringWithPrettyPrint:(BOOL) prettyPrint {
     NSError *error;
     NSData *jsonData = [NSJSONSerialization dataWithJSONObject:self
                                                   options:(NSJSONWritingOptions)    (prettyPrint ? NSJSONWritingPrettyPrinted : 0)
                                                     error:&error];

     if (! jsonData) {
        NSLog(@"%s: error: %@", __func__, error.localizedDescription);
        return @"{}";
     } else {
        return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
     } 
 }
@end

.

@interface NSArray (BVJSONString)
- (NSString *)bv_jsonStringWithPrettyPrint:(BOOL)prettyPrint;
@end

.

@implementation NSArray (BVJSONString)
-(NSString*) bv_jsonStringWithPrettyPrint:(BOOL) prettyPrint {
    NSError *error;
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:self
                                                       options:(NSJSONWritingOptions) (prettyPrint ? NSJSONWritingPrettyPrinted : 0)
                                                         error:&error];

    if (! jsonData) {
        NSLog(@"%s: error: %@", __func__, error.localizedDescription);
        return @"[]";
    } else {
        return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    }
}
@end
Walkyrie answered 28/11, 2013 at 9:30 Comment(4)
if we create a category of NSObject and put the same method, it works for both NSArray and NSDictionary. No need to write two separate files/interfaces. And it should return nil in case of error.Grannias
Why do you assume that NSUTF8StringEncoding is the correct encoding?Injudicious
Nevermind, the documentation says "The resulting data is a encoded in UTF-8."Injudicious
@AbdullahUmer That's what I've done too as I presume it'll also work on NSNumber, NSString, and NSNull – will find out in a minute or two!Philemol
H
67

To convert a NSDictionary to a NSString:

NSError * err;
NSData * jsonData = [NSJSONSerialization dataWithJSONObject:myDictionary options:0 error:&err]; 
NSString * myString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
Hind answered 21/3, 2014 at 10:47 Comment(0)
F
34

NOTE: This answer was given before iOS 5 was released.

Get the json-framework and do this:

#import "SBJsonWriter.h"

...

SBJsonWriter *jsonWriter = [[SBJsonWriter alloc] init];

NSString *jsonString = [jsonWriter stringWithObject:myDictionary];  

[jsonWriter release];

myDictionary will be your dictionary.

Florina answered 16/6, 2011 at 8:21 Comment(3)
Thanks for your response. Can you please suggest me how to add the framework to my application, looks like there are so many folder in the stig-json-framework-36b738fWorsen
@ChandraSekhar after cloning the git repository, it should suffice to add the Classes/ folder to your project.Florina
I just wrote #11765537 to fully illustrate this. Include error checking and some pieces of advise.Jephthah
W
28

You can also do this on-the-fly by entering the following into the debugger

po [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:yourDictionary options:1 error:nil] encoding:4];
Whispering answered 29/11, 2013 at 13:23 Comment(3)
Hard coded constants are a bit scary. Why not use NSUTF8StringEncoding etc.?Latchkey
That doesn't currently work in LLDB: error: use of undeclared identifier 'NSUTF8StringEncoding'Whispering
Perfect for those moments where you quickly want to inspect a dictionary with an external json editor!Salol
B
16

You can pass array or dictionary. Here, I am taking NSMutableDictionary.

NSMutableDictionary *contentDictionary = [[NSMutableDictionary alloc]init];
[contentDictionary setValue:@"a" forKey:@"b"];
[contentDictionary setValue:@"c" forKey:@"d"];

To generate a JSON string from a NSDictionary or NSArray, You don't need to import any third party framework. Just use following code:-

NSError *error; 
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:contentDictionary // Here you can pass array or dictionary
                    options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string
                    error:&error];
NSString *jsonString;
if (jsonData) {
    jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    //This is your JSON String
    //NSUTF8StringEncoding encodes special characters using an escaping scheme
} else {
    NSLog(@"Got an error: %@", error);
    jsonString = @"";
}
NSLog(@"Your JSON String is %@", jsonString);
Bil answered 11/12, 2015 at 6:55 Comment(0)
R
12
NSMutableDictionary *contentDictionary = [[NSMutableDictionary alloc]init];
        [contentDictionary setValue:@"a" forKey:@"b"];
        [contentDictionary setValue:@"c" forKey:@"d"];
        NSData *data = [NSJSONSerialization dataWithJSONObject:contentDictionary options:NSJSONWritingPrettyPrinted error:nil];
        NSString *jsonStr = [[NSString alloc] initWithData:data
                                                  encoding:NSUTF8StringEncoding];
Ralfston answered 18/9, 2014 at 11:9 Comment(1)
When I pass this to POST request as a parameter, I'm recieveing +[NSJSONSerialization dataWithJSONObject:options:error:]: Invalid top-level type in JSON write' error. Using XCode 9.0Opalescent
A
7

In Swift (version 2.0):

class func jsonStringWithJSONObject(jsonObject: AnyObject) throws -> String? {
    let data: NSData? = try? NSJSONSerialization.dataWithJSONObject(jsonObject, options: NSJSONWritingOptions.PrettyPrinted)

    var jsonStr: String?
    if data != nil {
        jsonStr = String(data: data!, encoding: NSUTF8StringEncoding)
    }

    return jsonStr
}
Anthelion answered 21/10, 2015 at 17:0 Comment(0)
W
3

Now no need third party classes ios 5 introduced Nsjsonserialization

NSString *urlString=@"Your url";
NSString *urlUTF8 = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url=[[NSURL alloc]initWithString:urlUTF8];
NSURLRequest *request=[NSURLRequest requestWithURL:url];

NSURLResponse *response;

NSData *GETReply = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];

NSError *myError = nil;

NSDictionary *res = [NSJSONSerialization JSONObjectWithData:GETReply options:NSJSONReadingMutableLeaves|| NSJSONReadingMutableContainers error:&myError];

Nslog(@"%@",res);

this code can useful for getting jsondata.

Weaks answered 28/11, 2013 at 12:20 Comment(1)
I think it's NSJSONReadingMutableLeaves | NSJSONReadingMutableContainers.Biquadrate
U
3

Here is the Swift 4 version

extension NSDictionary{

func toString() throws -> String? {
    do {
        let data = try JSONSerialization.data(withJSONObject: self, options: .prettyPrinted)
        return String(data: data, encoding: .utf8)
    }
    catch (let error){
        throw error
    }
}

}

Usage Example

do{
    let jsonString = try dic.toString()
    }
    catch( let error){
        print(error.localizedDescription)
    }

Or if you are sure it is valid dictionary then you can use

let jsonString = try? dic.toString()
Ulrikeulster answered 15/6, 2018 at 10:13 Comment(2)
This wont perform like the requested question, prettyPrint retains the spacing when attempting to squash into a string.Minister
let data = try JSONSerialization.data(withJSONObject: self, options: .fragmentsAllowed)Nations
C
3

This will work in swift4 and swift5.

let dataDict = "the dictionary you want to convert in jsonString" 

let jsonData = try! JSONSerialization.data(withJSONObject: dataDict, options: JSONSerialization.WritingOptions.prettyPrinted)

let jsonString = NSString(data: jsonData, encoding: String.Encoding.utf8.rawValue)! as String

print(jsonString)
Coloquintida answered 3/12, 2019 at 8:32 Comment(0)
I
1

As of ISO7 at least you can easily do this with NSJSONSerialization.

Isoniazid answered 13/2, 2014 at 10:41 Comment(1)
this is actually available as of iOS 5.0, not 7.0, according to the link.Ema
E
1

In Swift, I've created the following helper function:

class func nsobjectToJSON(swiftObject: NSObject) {
    var jsonCreationError: NSError?
    let jsonData: NSData = NSJSONSerialization.dataWithJSONObject(swiftObject, options: NSJSONWritingOptions.PrettyPrinted, error: &jsonCreationError)!

    if jsonCreationError != nil {
        println("Errors: \(jsonCreationError)")
    }
    else {
        // everything is fine and we have our json stored as an NSData object. We can convert into NSString
        let strJSON : NSString =  NSString(data: jsonData, encoding: NSUTF8StringEncoding)!
        println("\(strJSON)")
    }
}
Evelineevelinn answered 21/6, 2015 at 9:0 Comment(0)
B
-1
public func jsonPrint(_ o: NSObject, spacing: String = "", after: String = "", before: String = "") {
    let newSpacing = spacing + "    "
    if o.isArray() {
        print(before + "[")
        if let a = o as? Array<NSObject> {
            for object in a {
                jsonPrint(object, spacing: newSpacing, after: object == a.last! ? "" : ",", before: newSpacing)
            }
        }
        print(spacing + "]" + after)
    } else {
        if o.isDictionary() {
            print(before + "{")
            if let a = o as? Dictionary<NSObject, NSObject> {
                for (key, val) in a {
                    jsonPrint(val, spacing: newSpacing, after: ",", before: newSpacing + key.description + " = ")
                }
            }
            print(spacing + "}" + after)
        } else {
            print(before + o.description + after)
        }
    }
}

This one is pretty close to original Objective-C print style

Basal answered 18/5, 2017 at 9:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.