2013-08-22 2 views
2

В настоящее время я пытаюсь передать данные из Twitter с помощью их потоковых API. Я приложил код ниже для создания моего NSData и добавления к нему по адресу didReceiveData. По какой-то причине каждый раз, когда didReceiveData получает ответ от Twitter, он добавляется в качестве нового корня JSON в NSData, поэтому, когда я пытаюсь разобрать NSData в структуру JSON, он взрывается.Objective-C NSURLConnection didReceiveData, создающий плохой JSON в NSData

Я не мог понять, что происходит, и отправил JSON в валидатор, и он отметил, что в JSON есть несколько корней. Как я могу изменить код, чтобы продолжить добавление к существующему корню JSON? Или есть более простой способ сделать десериализацию в JSON, когда в файле NSData есть несколько записей JSON?

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { 
    // A response has been received, this is where we initialize the instance var you created 
    // so that we can append data to it in the didReceiveData method 
    // Furthermore, this method is called each time there is a redirect so reinitializing it 
    // also serves to clear it 
    NSLog(@"Did receive response"); 
    _responseData = [[NSMutableData alloc] init]; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 
    // Append the new data to the instance variable you declared 
    NSLog(@"Did Receive data"); 
    [_responseData appendData:data]; 
} 
+0

Сравните аналогичную проблему с http://stackoverflow.com/questions/18362889/error-deserializing-json-stream (и следующим обсуждением). Кажется, что NSJSONSerialization не может десериализовать один объект JSON из потока нескольких объектов JSON. –

+0

У вас есть несколько NSURLConnection, указывающих на один и тот же делегат? Возможно, вы загрузили более одного ответа. –

+0

@JamesRichard - это поток, который оставляет соединение открытым и получает структуры JSON с течением времени, которые добавляются в NSData ... вот в чем проблема. Я могу «найти способ» объединить все полученные json-структуры в один ». – Thomas

ответ

0

Просто, чтобы следить за этой темой для тех, кто имеет дело с одним и тем же: я закончил использование SBJson, у которого есть поддержка для потоковой передачи. http://superloopy.io/json-framework/

1

Я думаю, что вам нужна дополнительная логика для управления природой в реальном времени. Используйте NSMutableData в качестве контейнера для продолжения приема данных, но в конце каждой партии вы должны сканировать объект данных для всех допустимых объектов, создавать их и хранить в другом объекте, который содержит все встроенные объекты json. В этом примере предположим, у вас есть эта Ивара: NSMutableArray * _wholeObjects

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 
    // Append the new data to the instance variable you declared 
    NSLog(@"Did Receive data"); 
    [_responseData appendData:data]; 
    [self buildWholeObjects] 
} 

- (void) buildWholeObjects { 
    NSArray *rootObjects = <#business logic to return one whole JSON object per array element, or return nil if none found#> 
    if (rootObjects != nil) { 
    NSUInteger bytesExtracted = 0; 
    for (rootObject in rootObjects) { 
     [_wholeObjects addElement:rootObject]; 
     bytesExtracted += rootObject.length; 
    } 
    NSData *remainingData = [_responseData subdataWithRange:NSMakeRange(bytesExtracted, _responseData.length - bytesExtracted]; 
    [_responseData setData:remainingData]; 
    } 
} 

После выполнения этого доступ только объекты в _wholeObjects, где каждый элемент представляет собой полностью корректный объект JSON, который вы можете десериализации или читать в любом случае вам нужно ,

Просто для ясности, позволяет сказать, что первый NSData представляет:

{"a":"2"}{"c":"5 

При обработке его _wholeObjects будет иметь один элемент, представляющий { «A»: «2»}, и _responseData теперь будет { "с": "5

Тогда следующий поток данных следует продолжать на объекте Позволяет сказать второй NSData является:

"} 

Теперь _responseData есть {" C ":" 5" }, потому что мы добавили новое сообщение на оставшееся старое сообщение. Мы выстраиваем это и получаем второй элемент в _wholeObjects, а _responseData будет пустым и готов к приему следующего набора данных.

Надеюсь, что это помогает. Я думаю, что сложная часть для вас будет определять, какая часть _responseData считается действительным объектом JSON. Если они достаточно просты, вы можете просто подсчитать количество открытий {/ [до закрытия} /] и вытащить эту подстроку.

Смежные вопросы