Ho usato Jackson estesamente sul lato server per convertire da POJO a JSON e mi chiedevo se esiste una libreria simile per Objective C/iPhone SDK e viceversa. L'obiettivo C fornisce una riflessione, quindi dovrebbe essere possibile creare qualcosa di simile a Jackson.Jackson equivalente per iPhone?
risposta
Si potrebbe provare GoldenFleece, che converte tra oggetti JSON e Objective-C utilizzando un modello di convenzione over-configuration ispirato a Jackson.
Questo è circa un anno troppo tardi per me e noto l'autopromozione, ma apprezzo il tuo impegno nello scrivere questa libreria. Lo stato attuale dell'arte era doloroso. –
Il new iOS 5 APIs fornisce una grande facilità nella lettura/scrittura di JSON. Questi sono essenzialmente un rehash di TouchJSON library che puoi utilizzare in iOS 4. Anche se non ho visto molto fuori che genererà oggetti POCO da un payload di esempio, puoi creare classi che sono solo una facciata per un'istanza NSDictionary
che le biblioteche di cui sopra torneranno.
Ad esempio:
@interface PBPhoto : NSObject {
NSDictionary* data_;
}
@property (nonatomic, retain, readonly) NSDictionary *data;
- (NSString*) photoId;
- (NSString*) userId;
- (NSString*) user;
- (NSString*) title;
- (id) initWithData:(NSDictionary*)data;
@end
Implementazione:
#import "PBPhoto.h"
#define PHOTO_ID @"id"
#define USER_ID @"user_id"
#define USER @"user"
#define TITLE @"title"
@implementation PBPhoto
@synthesize data = data_;
- (id) initWithData:(NSDictionary*)data {
if ((self = [super init])) {
self.data = data;
}
return self;
}
- (NSString*) photoId {
return [super.data objectForKey:PHOTO_ID];
}
- (NSString*) userId {
return [self.data objectForKey:USER_ID];
}
- (NSString*) user {
return [self.data objectForKey:USER];
}
- (NSString*) title {
return [self.data objectForKey:TITLE];
}
- (void) dealloc {
[data_ release];
[super dealloc];
}
@end
Sarebbe utile non dover implementare i getter per ogni proprietà di ogni classe. Ecco dove la riflessione può essere utile. –
Che Objective-C fornisce riflessione potrebbe essere l'eufemismo dell'anno, ma un sacco di roba è esposta solo dal basso livello C runtime e quindi è un po 'ottuso.
Supponendo che si vuole prendere un oggetto arbitrario e trasformarlo in JSON, probabilmente la cosa più intelligente è quello di creare un NSDictionary
come intermediario, quindi farlo passare per NSJSONSerialization
(oppure costruire la stringa di te stesso, perché tutte le terze parti le biblioteche sono piuttosto pesanti a causa dell'onere di poter deserializzare).
Così, ad esempio:
- (NSDictionary *)dictionaryOfPropertiesForObject:(id)object
{
// somewhere to store the results
NSMutableDictionary *result = [NSMutableDictionary dictionary];
// we'll grab properties for this class and every superclass
// other than NSObject
Class classOfObject = [object class];
while(![classOfObject isEqual:[NSObject class]])
{
// ask the runtime to give us a C array of the properties defined
// for this class (which doesn't include those for the superclass)
unsigned int numberOfProperties;
objc_property_t *properties =
class_copyPropertyList(classOfObject, &numberOfProperties);
// go through each property in turn...
for(
int propertyNumber = 0;
propertyNumber < numberOfProperties;
propertyNumber++)
{
// get the name and convert it to an NSString
NSString *nameOfProperty = [NSString stringWithUTF8String:
property_getName(properties[propertyNumber])];
// use key-value coding to get the property value
id propertyValue = [object valueForKey:nameOfProperty];
// add the value to the dictionary —
// we'll want to transmit NULLs, even though an NSDictionary
// can't store nils
[result
setObject:propertyValue ? propertyValue : [NSNull null]
forKey:nameOfProperty];
}
// we took a copy of the property list, so...
free(properties);
// we'll want to consider the superclass too
classOfObject = [classOfObject superclass];
}
// return the dictionary
return result;
}
quindi è possibile utilizzare + dataWithJSONObject:options:error:
sul NSJSONSerialization
con il dizionario restituito.
Per andare dall'altra parte, suppongo che useresti il metodo di codifica del valore chiave setValue:forKey:
, ottenendo chiavi e valori da un dizionario tramite allKeys
e valueForKey:
.
Grazie, sì, questo era quello che avevo in mente, ma speravo che qualcuno avesse fatto il duro lavoro per me. Penso che userò il tuo esempio come base e frullerò qualcosa su me stesso –
Giusto per essere chiari poiché potrebbe esserci una barriera linguistica qui; vuoi che il codice serializzi automaticamente gli oggetti in JSON, in base alle loro proprietà dichiarate? – Tommy
Sì, il contrario sarebbe utile anche perché il nostro server invia una risposta codificata JSON. –