SerializationOto krótki wpis o Serializacji i Deserializacji JSON-a w Objective-C. Komunikaty w usługach sieciowych  zwykle mają notację XML-ową lub JSON-ową.  JSON jest lżejszy jest on więc bardziej stosowany. Usługa sieciowa typu SOAP jest ciężka więc urządzenia mobilne lubią usługi sieciowe typu REST.

 

Przejdźmy jednak do Serializacja i Deserializacja .

Brew pozorom jest to dosyć zawansowany temat. Gdy chcemy zapisać nasz obiekt do pliku używamy serializacji. Gdy otrzymujemy komunikat i chcemy go przetłumaczyć używamy deserializacji.

To jest przykład bardziej tradycyjnej metody Serializacji i deserializacji bez żadnych pomocniczych bibliotek.

Być może kiedyś spróbuje osiągnąć to samo używając protokołu NSCoding. Chociaż ta metoda jest stworzona do zapisów obiektów na urządzeniu.

Podobnie jak w Androidzie najłatwiej serializuje się tablice i słowniki. Prawdopodobnie chciałbyś aby istniała już gotowa metoda, która by wydrukowała twoją istniejącą klasę do postaci JSON-a. Z tego co znalazłem istnieje pewna niestandardowa biblioteka, która może ci pomóc.

JsonModel

Przeciwnym wypadku będziesz musiał napisać swoje własne metody, które upraszczają twoje obiekty do postaci słowników i tablic.

Metoda dataWithJSONObject : options : errorklasy NSJSONSerialization potrafi serializować słowniki i tablice, które zawierają instancje zmiennych NSString, NSNumber, NSArray, NSDictionary jak i NSNull dla pustych wartości.

Żadnych złożonych typów żadnych własnych klas. Serializujemy własne utworzone słowniki i tablice.

Oto ukazujący prostą Serializacja JSON.

- (IBAction)btn_JsonSer_Click:(id)sender {
    
    NSMutableDictionary *dictionary =
    [NSMutableDictionary dictionaryWithDictionary:@{
     @"First Name" : @"Tom",
     @"Last Name" : @"Zdzisławski",
     @"Age" : @24
     }];
    
    NSArray *arrayOfTomsChildren = @[
                                         @"  Stefan Zdzisławski",
                                         @"  Shin-Chan Zdzisławski",
                                         @"  Katarzyna Zdzisławska",
                                         @"  Franko Zdzisławski",
                                         @"  Darek Zdzisławski"
                                         ];
    
    [dictionary setValue:arrayOfTomsChildren forKey:@"children"];
    
    NSError *error = nil;
    NSData *jsonData = [NSJSONSerialization
                        dataWithJSONObject:dictionary
                        options:NSJSONWritingPrettyPrinted
                        error:&error];
    
    if ([jsonData length] > 0 &&
        error == nil){
        
        NSLog(@"Udało się serializować słownik jako JSON");
        NSString *jsonString =
        [[NSString alloc] initWithData:jsonData
                              encoding:NSUTF8StringEncoding];
        NSLog(@"JSON String = %@", jsonString);
        
    }
    else if ([jsonData length] == 0 &&
             error == nil){
        
        NSLog(@"Nic nie zostało zwrócone po serializacji");
        
    }
    else if (error != nil){
        
        NSLog(@"Błą∂ Sorry = %@", error);
        
    }
}

Jak widzisz słownik zawiera pierwsze imie, nazwisko oraz wiek Tom-a. Klucz o nazwie “children” zawiera listę dzieci Tom-a.

Wartością zwracaną przez metodę dataWithJSONObject : options : error jest NSData. NSData może być w łatwy sposób przekonwertowany do NSString używając inicjatora initWithData:encoding:

Oto wynik w konsoli powyższego kodu.

2013-06-25 20:13:49.741 iPhone_insert[6258:907] Udało się serializować słownik jako JSON
2013-06-25 20:13:49.746 iPhone_insert[6258:907] JSON String = {
  "Last Name" : "Zdzisławski",
  "First Name" : "Tom",
  "children" : [
    "  Stefan Zdzisławski",
    "  Shin-Chan Zdzisławski",
    "  Katarzyna Zdzisławska",
    "  Franko Zdzisławski",
    "  Darek Zdzisławski"
  ],
  "Age" : 24
}

Udało serializować obiekt równie dobrze możemy go zdeserializować używając metody JSONObjectWithData:options:error:klasy NSJSONSerialization.

Obiekt zwrócony przez tą metodę będzie albo słownikiem albo tablicą w zależność od struktury JSONA.

Poniżej znajduję mix kodu serializującego i deserializującego. Najpierw serializuje słownik do obiektu JSON potem go zdeserializuje do słownika. Na końcu wyświetlam wyniki metod.

- (IBAction)btn_DescJsonClick:(id)sender {
    
    NSMutableDictionary *dictionary =
    [NSMutableDictionary dictionaryWithDictionary:@{
     @"First Name" : @"Tom",
     @"Last Name" : @"Zdzisławski",
     @"Age" : @24
     }];
    
    NSArray *arrayOfTomsChildren = @[
                                     @"  Stefan Zdzisławski",
                                     @"  Shin-Chan Zdzisławski",
                                     @"  Katarzyna Zdzisławska",
                                     @"  Franko Zdzisławski",
                                     @"  Darek Zdzisławski"
                                     ];
    
    [dictionary setValue:arrayOfTomsChildren forKey:@"children"];
    
    NSError *error = nil;
    NSData *jsonData = [NSJSONSerialization
                        dataWithJSONObject:dictionary
                        options:NSJSONWritingPrettyPrinted
                        error:&error];
    
    /* Deserializacja */
    
    id jsonObject = [NSJSONSerialization
                     JSONObjectWithData: jsonData
                     options:NSJSONReadingAllowFragments
                     error:&error ];
    
    if (jsonObject != nil &&
        error == nil ){
        NSLog(@"Sukces desarilazcji..." );
        if ([jsonObject isKindOfClass:[NSDictionary class ]]){
            NSDictionary *deserializedDictionary = (NSDictionary *)jsonObject ;
            NSLog(@"Deserialized JSON Dictionary = %@" , deserializedDictionary);
        }
        else if ([jsonObject isKindOfClass:[NSArray class ]]){
            NSArray *deserializedArray = (NSArray *)jsonObject ;
            NSLog(@"Deserialized JSON Array = %@" , deserializedArray);
        } else {
            /* Jakiś inny obiekt został zwrócony. To nie powinno się zdarzyć */
        }
    }
    else if (error != nil){
        NSLog(@"Błąd w trakcie desarlizacji" );
    }    
}

Istnieje kilka opcji parametrów dla metody  JSONObjectithData:options:error  klasy.NSJSONSerialization.

Klauzura options akceptuje  następujące wartości:

  • NSJSONReadingMutableContainers.
    • Słownik albo tablica może zostać zwrócona przez metodę JSONObjectWithData:options:error:.Mówiąc prościej ta metoda zwróci albo instancje NSMutableArray albo NSMutableDictionary. Każda z tych kolekcji może być modyfikowana “Mutable”.
  • NSJSONReadingMutableLeaves 
    • Wartość ukazana w postaci drzewa jako napis NSMutableString.
  • NSJSONReadingAllowFragments 
    • Pozwala na deserializację danych JSON których element root nie jest słownikiem lub tablicą.

W tym wypadku użyłem opcji NSJSONReadingAllowFragments   gdyż element root nie jest słownikiem ani tablicą.

Oto wynik deserializacji.

2013-06-25 20:24:05.218 iPhone_insert[6287:907] Sukces deseralizacji...
2013-06-25 20:24:05.223 iPhone_insert[6287:907] Deserialized JSON Dictionary = {
    Age = 24;
    "First Name" = Tom;
    "Last Name" = "Zdzisławski";
    children =     (
        "  Stefan Zdzisławski",
        "  Shin-Chan Zdzisławski",
        "  Katarzyna Zdzisławska",
        "  Franko Zdzisławski",
        "  Darek Zdzisławski"
    );
}

Miłego programowania na IPhona.