93 votes

JSON et les données de base sur l’iPhone

J'ai une base de données de l'objet graphique (composée de deux entités liées par une relation).

J'étais curieux, comme un relativement inexpérimentés développeur iPhone, si quelqu'un pourrait recommander une approche et une JSON mise en œuvre pour l'iPhone, qui me permettrait de:

1) convertir la base de données des enregistrements dans une chaîne JSON (tout en maintenant la relation entre les entités); et

2) convertir la chaîne JSON de retour dans la base de données des objets (de plus en préservant la relation entre les entités).

J'ai cherché, sans succès, pour un tutoriel/exemple de code sur ce point, de sorte que toute aide serait la bienvenue.

103voto

Marcus S. Zarra Points 32178

Tout d'abord, choisir une librairie JSON à utiliser, personnellement, j'aime TouchJSON mais plusieurs autres sont très belles aussi. La partie compliquée, bien que pas très dur, est de convertir vos objets gérés en place des structures adéquates pour la conversion. J'ai écrit ça vite fait, donc il peut avoir une erreur ou deux :)

Les méthodes que vous appelez sont:

- (NSString*)jsonStructureFromManagedObjects:(NSArray*)managedObjects;
- (NSArray*)managedObjectsFromJSONStructure:(NSString*)json withManagedObjectContext:(NSManagedObjectContext*)moc;

Et la mise en œuvre est comme suit:

- (NSDictionary*)dataStructureFromManagedObject:(NSManagedObject*)managedObject
{
  NSDictionary *attributesByName = [[managedObject entity] attributesByName];
  NSDictionary *relationshipsByName = [[managedObject entity] relationshipsByName];
  NSMutableDictionary *valuesDictionary = [[managedObject dictionaryWithValuesForKeys:[attributesByName allKeys]] mutableCopy];
  [valuesDictionary setObject:[[managedObject entity] name] forKey:@"ManagedObjectName"];
  for (NSString *relationshipName in [relationshipsByName allKeys]) {
    NSRelationshipDescription *description = [[[managedObject entity] relationshipsByName] objectForKey:relationshipName];
    if (![description isToMany]) {
      NSManagedObject *relationshipObject = [managedObject valueForKey:relationshipName];
      [valuesDictionary setObject:[self dataStructureForManagedObject:relationshipObject] forKey:relationshipName];
      continue;
    }
    NSSet *relationshipObjects = [managedObject objectForKey:relationshipName];
    NSMutableArray *relationshipArray = [[NSMutableArray alloc] init];
    for (NSManagedObject *relationshipObject in relationshipObjects) {
      [relationshipArray addObject:[self dataStructureForManagedObject:relationshipObject]];
    }
    [valuesDictionary setObject:relationshipArray forKey:relationshipName];
  }
  return [valuesDictionary autorelease];
}

- (NSArray*)dataStructuresFromManagedObjects:(NSArray*)managedObjects
{
  NSMutableArray *dataArray = [[NSArray alloc] init];
  for (NSManagedObject *managedObject in managedObjects) {
    [dataArray addObject:[self dataStructureForManagedObject:managedObject]];
  }
  return [dataArray autorelease];
}

- (NSString*)jsonStructureFromManagedObjects:(NSArray*)managedObjects
{
  NSArray *objectsArray = [self dataStructuresFromManagedObjects:managedObjects];
  NSString *jsonString = [[CJSONSerializer serializer] serializeArray:objectsArray];
  return jsonString;
}

- (NSManagedObject*)managedObjectFromStructure:(NSDictionary*)structureDictionary withManagedObjectContext:(NSManagedObjectContext*)moc
{
  NSString *objectName = [structureDictionary objectForKey:@"ManagedObjectName"];
  NSManagedObject *managedObject = [NSEntityDescription insertNewObjectForEntityForName:objectName inManagedObjectContext:moc];
  [managedObject setValuesForKeysWithDictionary:structureDictionary];

  for (NSString *relationshipName in [[[managedObject entity] relationshipsByName] allKeys]) {
    NSRelationshipDescription *description = [relationshipsByName objectForKey:relationshipName];
    if (![description isToMany]) {
      NSDictionary *childStructureDictionary = [structureDictionary objectForKey:relationshipName];
      NSManagedObject *childObject = [self managedObjectFromStructure:childStructureDictionary withManagedObjectContext:moc];
      [managedObject setObject:childObject forKey:relationshipName];
      continue;
    }
    NSMutableSet *relationshipSet = [managedObject mutableSetForKey:relationshipName];
    NSArray *relationshipArray = [structureDictionary objectForKey:relationshipName];
    for (NSDictionary *childStructureDictionary in relationshipArray) {
      NSManagedObject *childObject = [self managedObjectFromStructure:childStructureDictionary withManagedObjectContext:moc];
      [relationshipSet addObject:childObject];
    }
  }
  return managedObject;
}

- (NSArray*)managedObjectsFromJSONStructure:(NSString*)json withManagedObjectContext:(NSManagedObjectContext*)moc
{
  NSError *error = nil;
  NSArray *structureArray = [[CJSONDeserializer deserializer] deserializeAsArray:json error:&error];
  NSAssert2(error == nil, @"Failed to deserialize\n%@\n%@", [error localizedDescription], json);
  NSMutableArray *objectArray = [[NSMutableArray alloc] init];
  for (NSDictionary *structureDictionary in structureArray) {
    [objectArray addObject:[self managedObjectFromStructure:structureDictionary withManagedObjectContext:moc]];
  }
  return [objectArray autorelease];
}

Maintenant, c'est récursive de sorte que vous pouvez facilement traduire la totalité de votre magasin persistant si vous n'êtes pas prudent. Regarder vos relations et de s'assurer qu'ils ne vont "vers le bas" l'objet de l'arbre, de sorte que vous obtenez seulement les objets que vous souhaitez traduire.

12voto

creativeKoder Points 189

Je voulais juste signaler une petite faute de frappe, qui a provoqué le code en panne, et j’espère que cela vous permettra d’économiser quelques min.

Le``

devrait vraiment être``

C’est tout.

Merci

10voto

Synchronisation de Base de Données avec des Rails est une présentation détaillée qui inclut des exemples de code pour la sérialisation/désérialisation de votre Base de Données d'objets/de JSON (passez à la diapositive 55 pour la Base de Données). Son exemple de code suppose une assez simple modèle sans relations, même si je pense qu'il serait assez facile à étendre.

La présentation va également dans quelques détails au sujet de garder votre Cœur de modèle de Données en synchronisation avec un REPOS de l'application web, avec des liens vers certains des bibliothèques utiles, y compris ObjectiveResource et ASIHTTPRequest. Vous ne savez pas si c'est ce que vous êtes en train de faire, mais il vaut la peine de regarder, même pour la Base de Données de code.

7voto

joshaidan Points 1368

Si vous avez un NSDate dans votre objet managé, comme déjà mentionné dans un des commentaires, vous aurez des problèmes Sérialisez l’objet contenant le NSDate. Une solution simple consiste à ajouter une méthode de JSONDataRepresentation à NSDate utilisant les catégories de l’objectif-c.

Ajouter ces deux fichiers à votre projet :

NSdate.h :

NSDate.m :

2voto

Il y a une lib qui effectue la synchronisation JSON pour vous : https://github.com/sixdegrees/lidenbrock

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X