Générer une chaîne JSON à partir de NSDictionary dans iOS

338

J'ai un dictionarybesoin de générer un JSON stringen utilisant dictionary. Est-il possible de le convertir? Pouvez-vous aider les gars à ce sujet?

ChandraSekhar
la source
3
@RicardoRivaldo c'est ça
QED
18
toute personne venant ici de la recherche google, veuillez lire la réponse ci-dessous par @Guillaume
Mahendra Liya

Réponses:

233

Voici des catégories pour NSArray et NSDictionary pour rendre cela super facile. J'ai ajouté une option pour la jolie impression (nouvelles lignes et onglets pour faciliter la lecture).

@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
Ben Clayton
la source
8
si nous créons une catégorie de NSObject et mettons la même méthode, cela fonctionne pour NSArray et NSDictionary. Pas besoin d'écrire deux fichiers / interfaces distincts. Et il devrait retourner nul en cas d'erreur.
Abdullah Umer
Pourquoi supposez-vous que NSUTF8StringEncodingc'est le bon encodage?
Heath Borders du
5
Peu importe, la documentation dit "Les données résultantes sont encodées en UTF-8".
Heath Borders du
@AbdullahUmer Voilà ce que je l' ai fait aussi que je suppose que ça va aussi travailler sur NSNumber, NSStringet NSNull- trouveront dans une minute ou deux!
Benjohn
756

Apple a ajouté un analyseur et sérialiseur JSON dans iOS 5.0 et Mac OS X 10.7. Voir NSJSONSerialization .

Pour générer une chaîne JSON à partir d'un NSDictionary ou NSArray, vous n'avez plus besoin d'importer de framework tiers.

Voici comment faire:

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];
}
Guillaume
la source
88
C'est un bon conseil ... c'est vraiment ennuyeux d'avoir des projets avec une tonne de bibliothèques tierces.
zakdances
3
Superbe solution de conversion en objet JSON. Excellent travail .. :)
MS.
1
+1 L'ajout en tant que catégorie à NSArrayet NSDictionaryrendrait sa réutilisation beaucoup plus simple.
devios1
comment reconvertir le json en dictionnaire?
OMGPOP
5
@OMGPOP - [NSJSONSerialization JSONObjectWithData:options:error:]retourne un objec de la Fondation à partir de données JSON données
Lukasz 'Severiaan' Grela
61

Pour convertir un NSDictionary en NSString:

NSError * err;
NSData * jsonData = [NSJSONSerialization dataWithJSONObject:myDictionary options:0 error:&err]; 
NSString * myString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
jobima
la source
34

REMARQUE: cette réponse a été donnée avant la sortie d'iOS 5.

Obtenez le framework json et procédez comme suit:

#import "SBJsonWriter.h"

...

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

NSString *jsonString = [jsonWriter stringWithObject:myDictionary];  

[jsonWriter release];

myDictionary sera votre dictionnaire.

Nick Weaver
la source
Merci pour votre réponse. Pouvez-vous me suggérer comment ajouter le framework à mon application, il semble qu'il y ait tellement de dossiers dans le stig-json-framework-36b738f
ChandraSekhar
@ChandraSekhar après le clonage du référentiel git, il devrait suffire d'ajouter le dossier Classes / à votre projet.
Nick Weaver
1
Je viens d'écrire stackoverflow.com/questions/11765037/… pour illustrer pleinement cela. Inclure la vérification des erreurs et quelques conseils.
Pascal
25

Vous pouvez également le faire à la volée en entrant ce qui suit dans le débogueur

po [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:yourDictionary options:1 error:nil] encoding:4];
Andy
la source
4
Les constantes codées en dur sont un peu effrayantes. Pourquoi ne pas utiliser NSUTF8StringEncoding etc.?
Ian Newson
5
Cela ne fonctionne pas actuellement dans LLDB:error: use of undeclared identifier 'NSUTF8StringEncoding'
Andy
2
Parfait pour les moments où vous souhaitez rapidement inspecter un dictionnaire avec un éditeur json externe!
Florian
15

Vous pouvez transmettre un tableau ou un dictionnaire. Ici, je prends NSMutableDictionary.

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

Pour générer une chaîne JSON à partir d'un NSDictionary ou NSArray, vous n'avez pas besoin d'importer de framework tiers. Utilisez simplement le code suivant: -

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);
Rencontrez Doshi
la source
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];
user2885077
la source
Lorsque je passe cela à la requête POST en tant que paramètre, je reçois une +[NSJSONSerialization dataWithJSONObject:options:error:]: Invalid top-level type in JSON write'erreur. Utilisation de XCode 9.0
Daya Kevin
7

Dans 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
}
Roi-sorcier
la source
3

Maintenant, pas besoin de classes tierces ios 5 a introduit 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);

ce code peut être utile pour obtenir des jsondata.

chowdary mahesh
la source
Je pense que oui NSJSONReadingMutableLeaves | NSJSONReadingMutableContainers.
afp
1

Dans Swift, j'ai créé la fonction d'assistance suivante:

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)")
    }
}
James Laurenstin
la source
1

Depuis ISO7 au moins, vous pouvez facilement le faire avec NSJSONSerialization .

Jeef
la source
cela est en fait disponible depuis iOS 5.0, pas 7.0, selon le lien.
manroe
1

Voici le 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
    }
}

}

Exemple d'utilisation

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

Ou si vous êtes sûr qu'il s'agit d'un dictionnaire valide, vous pouvez utiliser

let jsonString = try? dic.toString()
levin varghese
la source
Cela ne fonctionnera pas comme la question demandée, prettyPrint conserve l'espacement lorsque vous essayez de vous écraser dans une chaîne.
Sean Lintern
1

Cela fonctionnera dans swift4 et 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)
azeem usmani
la source
-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)
        }
    }
}

Celui-ci est assez proche du style d'impression Objective-C original

markov
la source