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?


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

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];
}

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];

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.


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];

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);

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];

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
}

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.


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)")
    }
}


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()

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)

-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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.