如何解决 RestKit JSON 序列化问题

Posted

技术标签:

【中文标题】如何解决 RestKit JSON 序列化问题【英文标题】:How can I fix RestKit JSON serialization issue 【发布时间】:2014-05-01 14:23:44 【问题描述】:

我正在尝试使用 RestKit 0.2 将一组 json 对象(有时该数组仅包含一个对象)发布到 REST 服务

对于具有一个对象的数组,我想要发送到服务的内容应该如下所示:

[
      
         "Latitude":0,
         "Location":"Nowhere, FL",
         "Id":25699,
         "Version":0,
         "Name":"TEST Customer Airport 2 created by tstUser",
         "TimeZone":":America\/New York",
         "Longitude":0,
         "Code":"XXXX987",
         "IsUserDefinedAirportCode":true
      
]

根据跟踪输出,这是 RestKit 在 request.body 中发送的内容:


   "\/AirportCode\/UpsertCustomerAirportCodes":[
      
         "Latitude":0,
         "Location":"Nowhere, FL",
         "Id":25699,
         "Version":0,
         "Name":"TEST Customer Airport 2 created by tstUser",
         "TimeZone":":America\/New York",
         "Longitude":0,
         "Code":"XXXX987",
         "IsUserDefinedAirportCode":true
      
   ]

json 的第一个元素是我正在调用的服务的资源/操作路径。为什么 RestKit 将其放入 Json 中?

详情...

为了发送这个,我有一个 ApiAirportCode 模型对象:

#import <Foundation/Foundation.h>

@interface ApiAirportCode : NSObject <NSCoding>

@property (nonatomic, copy) NSString *Code;
@property (nonatomic, copy) NSNumber *Id;
@property (nonatomic, copy) NSNumber *Latitude;
@property (nonatomic, copy) NSString *Location;
@property (nonatomic, copy) NSNumber *Longitude;
@property (nonatomic, copy) NSString *Name;
@property (nonatomic, copy) NSString *TimeZone;
@property (nonatomic, assign) bool IsUserDefinedAirportCode;

@end

这是映射:

RKObjectMapping* airportCodePostMap = [RKObjectMapping mappingForClass:[ApiAirportCode class]];
[airportCodePostMap addAttributeMappingsFromArray:@[@"Code", @"Id", @"Latitude", @"Location", @"Longitude", @"Name", @"TimeZone", @"IsUserDefinedAirportCode"]];
RKRequestDescriptor* airportCodePostReqDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[airportCodePostMap inverseMapping] objectClass:[ApiAirportCode class] rootKeyPath:@"/AirportCode/UpsertCustomerAirportCodes" method:RKRequestMethodPOST];
[_ObjectManager addRequestDescriptor:airportCodePostReqDescriptor];

这是对服务的调用:

- (void) saveCustomAirportCodesToServer:(NSArray*) customAirports

    _ObjectManager.requestSerializationMIMEType=RKMIMETypeJSON;
    [_ObjectManager postObject:customAirports path:@"/AirportCode/UpsertCustomerAirportCodes" parameters:NULL success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) 

        // Do something


     failure:^(RKObjectRequestOperation *operation, NSError *error) 

        ApiPayload* errorPld = [[error userInfo] objectForKey:RKObjectMapperErrorObjectsKey][0];

    ];

    // Do something...

这是来自 RestKit 的跟踪输出:

2014-05-01 10:17:39.286 Flightdocs[2447:60b] D restkit.object_mapping:RKMappingOperation.m:952 开始映射 操作... 2014-05-01 10:17:39.287 Flightdocs[2447:60b] T restkit.object_mapping:RKMappingOperation.m:953 执行映射 操作:对于'__NSDictionaryM' 目的。从对象映射值 ((null)) 到对象 与对象映射 (null) 2014-05-01 10:17:39.287 Flightdocs[2447:60b] T restkit.object_mapping:RKMappingOperation.m:550 映射属性 值 keyPath '代码' 到 '代码' 2014-05-01 10:17:39.287 Flightdocs[2447:60b] T restkit.object_mapping:RKMappingOperation.m:572 从 keyPath 'Code' 到 'Code' 的映射属性值。值:XXXX98765 2014-05-01 10:17:39.287 Flightdocs[2447:12ef7] D restkit.object_mapping:RKPropertyInspector.m:130 缓存属性 检查“NSMutableDictionary”类: 文件HFSFlags = isPrimitive = 1; keyValueCodingClass = NSNumber; 名称=文件HFSFlags; ; 文件HFSResourceForkSize = isPrimitive = 1; keyValueCodingClass = NSNumber; 名称=文件HFSResourceForkSize; ; 2014-05-01 10:17:39.287 Flightdocs[2447:60b] T restkit.object_mapping:RKMappingOperation.m:550 映射属性 值 keyPath 'Id' 到 'Id' 2014-05-01 10:17:39.288 Flightdocs[2447:60b] T restkit.object_mapping:RKMappingOperation.m:572 从 keyPath 'Id' 到 'Id' 的映射属性值。价值:25699 2014-05-01 10:17:39.288 Flightdocs[2447:60b] T restkit.object_mapping:RKMappingOperation.m:550 映射属性 值 keyPath '纬度' 到 '纬度' 2014-05-01 10:17:39.288 Flightdocs[2447:60b] T restkit.object_mapping:RKMappingOperation.m:572 从 keyPath 'Latitude' 映射到 'Latitude' 的属性值。值:0 2014-05-01 10:17:39.288 Flightdocs[2447:60b] T restkit.object_mapping:RKMappingOperation.m:550 映射属性 值 keyPath 'Location' 到 'Location' 2014-05-01 10:17:39.288 Flightdocs[2447:60b] T restkit.object_mapping:RKMappingOperation.m:572 从 keyPath 'Location' 到 'Location' 的映射属性值。价值: 无处,佛罗里达州 2014-05-01 10:17:39.289 Flightdocs[2447:60b] T restkit.object_mapping:RKMappingOperation.m:550 映射属性 值 keyPath '经度' 到 '经度' 2014-05-01 10:17:39.289 Flightdocs[2447:60b] T restkit.object_mapping:RKMappingOperation.m:572 从 keyPath 'Longitude' 到 'Longitude' 的映射属性值。价值: 0 2014-05-01 10:17:39.289 Flightdocs[2447:60b] T restkit.object_mapping:RKMappingOperation.m:550 映射属性 值 keyPath '名称' 到 '名称' 2014-05-01 10:17:39.289 Flightdocs[2447:60b] T restkit.object_mapping:RKMappingOperation.m:572 从 keyPath 'Name' 到 'Name' 的映射属性值。值:测试 客户机场 2 由 tstUser 2014-05-01 10:17:39.289 创建 Flightdocs[2447:60b] T restkit.object_mapping:RKMappingOperation.m:550 将属性值 keyPath 'TimeZone' 映射到 'TimeZone' 2014-05-01 10:17:39.289 Flightdocs[2447:60b] T restkit.object_mapping:RKMappingOperation.m:572 映射的属性值 从 keyPath 'TimeZone' 到 'TimeZone'。价值::美国/纽约 2014-05-01 10:17:39.289 Flightdocs[2447:60b] T restkit.object_mapping:RKMappingOperation.m:550 映射属性 值 keyPath 'IsUserDefinedAirportCode' 到 'IsUserDefinedAirportCode' 2014-05-01 10:17:39.290 Flightdocs[2447:60b] T restkit.object_mapping:RKMappingOperation.m:572 映射的属性值 从 keyPath 'IsUserDefinedAirportCode' 到 'IsUserDefinedAirportCode'。 值:1 2014-05-01 10:17:39.290 Flightdocs[2447:60b] D restkit.network:RKObjectParameterization.m:128 序列化 __NSCFBoolean 值在 keyPath 到 __NSCFBoolean (1) 2014-05-01 10:17:39.290 Flightdocs[2447:60b] D restkit.object_mapping:RKMappingOperation.m:1021 完成映射 操作成功... 2014-05-01 10:17:39.294 Flightdocs[2447:60b] T restkit.network:RKObjectRequestOperation.m:178 POST 'https://rsw-dev-05.flightdocs.com/AirportCode/UpsertCustomerAirportCodes': 请求头= 接受 = "应用程序/json"; "接受语言" = "en;q=1, fr;q=0.9, de;q=0.8, zh-Hans;q=0.7, zh-Hant;q=0.6, ja;q=0.5"; 授权= “承载1QgmbgUMk5Z-g5W8BtDZjOIok_NIAVuaL9b6kJJybdObQv3MZVShxWS098L1M1iP7DcGsV2nYfIK-FE6409hPN8WVQAJdNwh1VKRCY0STTKpViKown53Mq0B5cl-EbgIhBOF0LvTf0xwQnsLBAOl-21QYmZyNzfEbXGNhNuX3Cn06oHdZIzxLvpvwTATnVG-hCTQvAl04Oh3wzKWu3UAt7Nnbe_pZDIhLCpPFwyIw3aI2ife5fbWpoEcRBGbU0Bob8o2vrCciQiLWPCqsN2sepztD6A1XIPWObPhgn2sBGyrgSaJN_MyG6141UAKGBTDyYPWVMIVA6wx-AFtc6116goKtHc-FV7COJl_TuAWw7itc-543Rgmu_m1jKmRQT78bzit1JxG_j0YsJ4nB2hVHdUstV3QKAGiPUQl9PJxBRyHiUhwkRFwxIEAtSk9NsjfeehJJjaEq9Dr3jkfh6S8M6-AUa88q8DxNE-xman84dUsqeBBVigoVP-PGkgqv8fkU3DE2M4vVYdlyAHGvR8okA”; “内容类型”=“应用程序/json;字符集=utf-8”; "User-Agent" = "Flightdocs/1.4.7 (iPad Simulator; ios 7.1; Scale/1.00)"; request.body="/AirportCode/UpsertCustomerAirportCodes":["Id":25699,"Latitude":0,"Location":"Nowhere, FL","Name":"TEST Customer Airport 2 创建者 tstUser","TimeZone":":America/New York","Longitude":0,"Code":"XXXX98765","IsUserDefinedAirportCode":true]

【问题讨论】:

【参考方案1】:

我想通了……

我的问题是 RKRequestDescriptor requestDescriptorWithMapping 的 rootKeyPath 参数。这应该为零。

我传入资源/操作名称是因为我认为 RestKit 使用它来知道何时使用此请求描述符(就像使用 withPathPattern 参数映射响应一样)。不知道为什么不需要传递一些东西来指示 withPathPattern。

所以这行代码:

RKRequestDescriptor* airportCodePostReqDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[airportCodePostMap inverseMapping] objectClass:[ApiAirportCode class] rootKeyPath:@"/AirportCode/UpsertCustomerAirportCodes" method:RKRequestMethodPOST];

应该是

RKRequestDescriptor* airportCodePostReqDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:[airportCodePostMap inverseMapping] objectClass:[ApiAirportCode class] rootKeyPath:nil method:RKRequestMethodPOST];

【讨论】:

以上是关于如何解决 RestKit JSON 序列化问题的主要内容,如果未能解决你的问题,请参考以下文章

如何将展平的对象序列化回服务器,在 RestKit 中未展平

关于 RestKit 中的对象序列

如何使用带有 RKObjectMapping 的 RestKit 0.24 将本地 JSON 字符串映射到对象?

RESTKIT:反序列化 JSON 与并非所有关系属性

你如何在 RestKit 0.20 中使用 RKDotNetDateFormatter?

RestKit 自定义序列化