Generar cadena JSON desde NSDictionary en iOS


338

Tengo un dictionaryNecesito generar un JSON stringusando dictionary. ¿Es posible convertirlo? ¿Pueden por favor ayudarme en esto?


3
@RicardoRivaldo que es esto
QED

18
cualquier persona que venga de Google Search, lea la respuesta a continuación por @Guillaume
Mahendra Liya

Respuestas:


233

Aquí hay categorías para NSArray y NSDictionary para hacer esto súper fácil. He agregado una opción para impresión bonita (nuevas líneas y pestañas para que sea más fácil de leer).

@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 creamos una categoría de NSObject y ponemos el mismo método, funciona tanto para NSArray como para NSDictionary. No es necesario escribir dos archivos / interfaces separados. Y debería devolver nulo en caso de error.
Abdullah Umer

¿Por qué supone que esa NSUTF8StringEncodinges la codificación correcta?
Heath Borders

55
No importa, la documentación dice "Los datos resultantes están codificados en UTF-8".
Heath Borders

@AbdullahUmer eso es lo que he hecho demasiado ya que supongo que también va a trabajar en NSNumber, NSStringy NSNull- se encuentra en un minuto o dos!
Benjohn

756

Apple agregó un analizador y serializador JSON en iOS 5.0 y Mac OS X 10.7. Ver NSJSONSerialización .

Para generar una cadena JSON desde un NSDictionary o NSArray, ya no necesita importar ningún marco de terceros.

Aquí está cómo hacerlo:

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
Este es un buen consejo ... es realmente molesto tener proyectos que tengan un montón de bibliotecas de terceros.
zakdances

3
Excelente solución para convertir a objetos JSON. Buen trabajo .. :)
MS.

1
+1 Agregar esto como una categoría NSArrayy NSDictionaryharía que su reutilización sea mucho más simple.
devios1

¿Cómo convertir el JSON de nuevo al diccionario?
OMGPOP

55
@OMGPOP - [NSJSONSerialization JSONObjectWithData:options:error:]devuelve un objeto de la Fundación a partir de datos JSON dados
Lukasz 'Severiaan' Grela

61

Para convertir un NSDictionary en un NSString:

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

34

NOTA: Esta respuesta se dio antes del lanzamiento de iOS 5.

Obtenga el json-framework y haga esto:

#import "SBJsonWriter.h"

...

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

NSString *jsonString = [jsonWriter stringWithObject:myDictionary];  

[jsonWriter release];

myDictionary será tu diccionario


Gracias por su respuesta. Puede usted por favor me sugieren cómo agregar el marco de mi solicitud, parece que hay tantos carpeta en el Stig-JSON-marco-36b738f
Chandrasekhar

@ChandraSekhar después de clonar el repositorio git, debería ser suficiente agregar las Clases / carpeta a su proyecto.
Nick Weaver

1
Acabo de escribir stackoverflow.com/questions/11765037/… para ilustrar completamente esto. Incluye comprobación de errores y algunos consejos.
Pascal

25

También puede hacerlo sobre la marcha ingresando lo siguiente en el depurador

po [[NSString alloc] initWithData:[NSJSONSerialization dataWithJSONObject:yourDictionary options:1 error:nil] encoding:4];

44
Las constantes codificadas son un poco aterradoras. ¿Por qué no usar NSUTF8StringEncoding, etc.?
Ian Newson

55
Eso no funciona actualmente en LLDB:error: use of undeclared identifier 'NSUTF8StringEncoding'
Andy

2
¡Perfecto para esos momentos en los que desea inspeccionar rápidamente un diccionario con un editor json externo!
Florian

15

Puede pasar matriz o diccionario. Aquí, estoy tomando NSMutableDictionary.

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

Para generar una cadena JSON desde NSDictionary o NSArray, no es necesario importar ningún marco de terceros. Simplemente use el siguiente código: -

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

Cuando paso esto a la solicitud POST como parámetro, estoy recibiendo un +[NSJSONSerialization dataWithJSONObject:options:error:]: Invalid top-level type in JSON write'error. Usando XCode 9.0
Daya Kevin

7

En Swift (versión 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

Ahora no necesita clases de terceros ios 5 introdujo 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);

Este código puede ser útil para obtener jsondata.


Creo que es NSJSONReadingMutableLeaves | NSJSONReadingMutableContainers.
afp

1

En Swift, he creado la siguiente función auxiliar:

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

Aquí está la versión de Swift 4

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

}

Ejemplo de uso

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

O si está seguro de que es un diccionario válido, puede usar

let jsonString = try? dic.toString()

Esto no funcionará como la pregunta solicitada, prettyPrint conserva el espacio al intentar apretar en una cadena.
Sean Lintern

1

Esto funcionará en swift4 y 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)
        }
    }
}

Este es bastante parecido al estilo de impresión original de Objective-C

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.