SBJsonWriter Вложенный NSDictionary

Я пытаюсь выполнить сериализацию объекта objc с Json, чтобы отправить его на сервер.

Тот же сервер отправляет следующее в GET для этого типа объекта:

 {
   "TypeProperties":[
      {"Key":"prop 0","Value":"blah 0"},
      {"Key":"prop 1","Value":"blah 1"},
      {"Key":"prop 2","Value":"blah 2"},
      {"Key":"prop 3","Value":"blah 3"}
     ],
   "ImageURls":[
      {"Key":"url 0","Value":"blah 0"},
      {"Key":"url 1","Value":"blah 1"},
      {"Key":"url 2","Value":"blah 2"},
      {"Key":"url 3","Value":"blah 3"}
     ]
}

SBJsonWriter создает следующее для соответствующего объекта/типа, который я создал в objc:

{
  "TypeProperties": {
    "key 2": "object 2",
    "key 1": "object 1",
    "key 4": "object 4",
    "key 0": "object 0",
    "key 3": "object 3"
  },
  "ImageUrls": {
    "key 0": "url 0",
    "key 1": "url 1",
    "key 2": "url 2"
  }
}

Вот как я использую SBJsonWriter:

SBJsonWriter *writer = [[SBJsonWriter alloc] init];
writer.humanReadable = YES;
NSString* json = [writer stringWithObject:itemToAdd];

Здесь моя реализация proxyForJson в классе, который сериализуется (требуется SBJsonWriter):

- (NSDictionary*) proxyForJson
{
      return [NSMutableDictionary dictionaryWithObjectsAndKeys:
                self.typeProperties, @"TypeProperties",
                self.imageUrls, @"ImageUrls",
                nil];
}

Серийный класс содержит только два свойства: typeProperties и imageUrls (оба являются NSMutableDictionary).

Теперь проблема: сервер (неудивительно) не анализирует Json, созданный SBJsonWriter, когда я выполняю POST. И вопрос: как я могу создать Json, который соответствует тому, что предоставляется сервером (при условии, что совпадение Json будет корректно проанализировано при загрузке).

Заранее благодарим за помощь.

Ответ 1

В JSON { } представляет объект (пары ключ/значение) и [ ] представляет массив. Судя по представленному вами образцу, вот что ожидает ваш сервер:

Верхний объект: словарь с двумя клавишами: TypeProperties и ImageUrls.

TypeProperties и ImageUrls: каждый представляет собой массив, содержащий один или несколько объектов с двумя ключами: Key и Value. Каждая клавиша должна иметь соответствующее значение.

Чтобы соответствовать тому, что ожидает ваш сервер, вам нужна структура, подобная этой (обратите внимание, что это всего лишь простой пример, написанный прямо здесь, но должен указывать вам в правильном направлении):

NSDictionary *object = [NSDictionary dictionaryWithObjectsAndKeys:
                        @"prop 0", @"Key",
                        @"blah 0", @"Value",
                        nil];

NSArray *typeProperties = [NSArray arrayWithObjects:
                           object, // Add as many similar objects as you want
                           nil];

NSArray *imageUrls = [NSArray arrayWithObjects:
                      object, // Add as many similar objects as you want
                      nil];

Затем в вашем методе proxyForJson вы можете использовать:

- (NSDictionary*) proxyForJson
{
      return [NSDictionary dictionaryWithObjectsAndKeys:
              typeProperties, @"TypeProperties",
              imageUrls, @"ImageUrls",
              nil];
}

Ответ 2

Вот простой код, демонстрирующий, как использовать SBJsonWriter:

#import <Foundation/Foundation.h>

#import "SBJsonWriter.h"


int main(int argc, const char * argv[])
{

    @autoreleasepool {

        NSDictionary* aNestedObject = [NSDictionary dictionaryWithObjectsAndKeys:
                                              @"nestedStringValue", @"aStringInNestedObject",
                                              [NSNumber numberWithInt:1], @"aNumberInNestedObject",
                                         nil];

        NSArray * aJSonArray = [[NSArray alloc] initWithObjects: @"arrayItem1", @"arrayItem2", @"arrayItem3", nil];

        NSDictionary * jsonTestDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                             @"stringValue", @"aString",
                                             [NSNumber numberWithInt:1], @"aNumber",
                                             [NSNumber numberWithFloat:1.2345f], @"aFloat",
                                             [[NSDate date] description], @"aDate",
                                             aNestedObject, @"nestedObject",
                                             aJSonArray, @"aJSonArray",
                                             nil];

        // create JSON output from dictionary

        NSError *error = nil;
        NSString * jsonTest = [[[SBJsonWriter alloc] init] stringWithObject:jsonTestDictionary error:&error];

        if ( ! jsonTest ) {
            NSLog(@"Error: %@", error);
        }else{
            NSLog(@"%@", jsonTest);
        } 
    }
    return 0;
}

выходы

{
    "aDate":"2012-09-12 07:39:00 +0000",
    "aFloat":1.2345000505447388,
    "nestedObject":{
        "aStringInNestedObject":"nestedStringValue",
        "aNumberInNestedObject":1
     },
    "aJSonList":["arrayItem1","arrayItem2","arrayItem3"],
    "aString":"stringValue",
    "aNumber":1
}

Примечания:

  • Использование 'error' позволило мне понять, что если вы пишете [NSDate date] вместо описания [[NSDate date]] вы получите "JSON сериализация не поддерживается для __NSTaggedDate ".
  • Обратите внимание на ошибку округления округления... 1.2345 стал 1.2345000505447388