请跳过此部分至更新3。
环境:iOS7.1,MagicalRecord,Restkit,Mogenerator
所需的JSON表单如下所示:
{"amount":[10,20,50]} (set of TSNDecimal's in TSNTagAmountRequest)
请求中涉及以下实体:
@interface TSNTagAmountRequest: NSManagedObject
@property (nonatomic, strong) NSSet *amount;
@end
其中金额集合设置为TSNDecimal':
@interface TSNDecimal: NSManagedObject
@property (nonatomic, strong) NSDecimalNumber* number;
@end
名称数字的十进制数字是帮助者。
TSKecimal的RKObjectMapping:
RKEntityMapping *decimalMapping = [RKEntityMapping
mappingForEntityForName:@"TSNDecimal"
inManagedObjectStore:managedObjectStore];
// map the value in JSON directly to the helper "number"
[decimalMapping addPropertyMapping:
[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:@"number"]];
上一行是我希望正确反序列化的代码"数量":[10,20,50]到三个TSNDecimal分别到数字属性(它工作),它也应该从TSNDecimal(通过数字)到JSON的顺序序列化:"金额":[10,20 ..]它解析响应时有效但不是为了请求。
其余的是关系映射:
RKPropertyMapping* decimalPropertyMappingAmount =
[RKRelationshipMapping relationshipMappingFromKeyPath:@"amount"
toKeyPath:@"amount"
withMapping:decimalMapping];
(我也试过FromKeyPath:@" amount.number" toKeyPath:@" amount"但由于向KVC传递了错误的路径而引发了异常([self.object] valueForKey:键]))
最后我定义了TSNTagAmountRequest和TSNDecimal之间的关系: tagAmountRequestMapping = [RKObjectMapping requestMapping]; [tagAmountRequestMapping addPropertyMapping:decimalPropertyMappingAmount];
并将描述符添加到RK管理器:
requestDescriptor = [RKRequestDescriptor
requestDescriptorWithMapping:tagAmountRequestMapping
objectClass:[TSNTagAmountRequest class]
rootKeyPath:nil
method:RKRequestMethodPOST];
[_rkManager addRequestDescriptor:requestDescriptor];
问题是 NSJSONSerialization dataWithJSONObject:optionserror:中出现异常显然是因为TSNDecimal未从TSNDecimal.number转换为NSJSONSerialization理解的NSDecimalNumber。
例外: JSON写入中的类型无效(TSNDecimal) ,因为RKNSJSONSerialization中dataFromObject中的数据包含由RKObjectMappingOperationDataSource创建的TSNDecimal对象(不是RKManagedObjectMappingOperationDataSource)
{
amount = (
"<TSNDecimal: 0xc1d0bf0> (entity: (null); id: (null) ; data: {\n})",
"<TSNDecimal: 0x11543080> (entity: (null); id: (null) ; data: {\n})"
);
}
我应该是NSDecimalNumber而不是TSNDecimal。
总之,我期待代码
[decimalMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:@"number"]];
完成其工作并翻译&#34;数字&#34;回到nil(即集合中未命名的项目),但它不能以这种方式工作。有这个example in the section Mapping Values without Key Paths但我很困惑使用 [RKResponseDescriptor responseDescriptorWithMapping:如果我想组成JSON主体。
可以很好地解析响应[decimalMapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil toKeyPath:@"number"]];
RKPropertyMapping* decimalPropertyMappingAmount =
[RKRelationshipMapping relationshipMappingFromKeyPath:@"amount"
toKeyPath:@"amount"
withMapping:decimalMapping];
为什么不提出要求?
我看到的问题是 CoreData:错误:无法在NSManagedObject类上调用指定的初始化程序&#39; TSNDecimal&#39;
使用
初始化核心数据对象TSNTagAmountRequest* request = [TSNTagAmountRequest requestWithModel:self];
TSNDecimal* decimalEntity = nil;
for(NSDecimalNumber* number in amount) {
decimalEntity = [TSNDecimal MR_createEntity];
decimalEntity.number = number;
[request addAmountObject:decimalEntity];
}
这是日志:
D restkit.object_mapping:RKMappingOperation.m:860 Starting mapping operation...
T restkit.object_mapping:RKMappingOperation.m:861 Performing mapping operation: <RKMappingOperation 0x9681ca0> for '__NSDictionaryM' object. Mapping values from object <TSNTagAmountRequest: 0xf7b8c90> (entity: TSNTagAmountRequest; id: 0xf784700 <x-coredata:///TSNTagAmountRequest/tB2DF8887-7E6C-420F-998A-D250751E5CED164> ; data: {
amount = (
"0x9664220 <x-coredata:///TSNDecimal/tB2DF8887-7E6C-420F-998A-D250751E5CED165>",
"0x9616390 <x-coredata:///TSNDecimal/tB2DF8887-7E6C-420F-998A-D250751E5CED166>"
);
}) ((null)) to object {
} with object mapping (null)
D restkit.object_mapping:RKMappingOperation.m:641 Mapping one to many relationship value at keyPath 'amount' to 'amount'
CoreData: error: Failed to call designated initializer on NSManagedObject class 'TSNDecimal'
T restkit.object_mapping:RKMappingOperation.m:542 Performing nested object mapping using mapping <RKRelationshipMapping: 0x95a0df0 amount => amount> for data: <TSNDecimal: 0x9652900> (entity: TSNDecimal; id: 0x9664220 <x-coredata:///TSNDecimal/tB2DF8887-7E6C-420F-998A-D250751E5CED165> ; data: {
number = 5;
})
D restkit.object_mapping:RKMappingOperation.m:860 Starting mapping operation...
T restkit.object_mapping:RKMappingOperation.m:861 Performing mapping operation: <RKMappingOperation 0x96b3d60> for 'TSNDecimal' object. Mapping values from object <TSNDecimal: 0x9652900> (entity: TSNDecimal; id: 0x9664220 <x-coredata:///TSNDecimal/tB2DF8887-7E6C-420F-998A-D250751E5CED165> ; data: {
number = 5;
}) ({
mapping = {
collectionIndex = 3221208359;
};
}) to object <TSNDecimal: 0x96b2880> (entity: (null); id: (null) ; data: {
}) with object mapping (null)
T restkit.object_mapping:RKMappingOperation.m:439 Found transformable value at keyPath '(null)'. Transforming from class 'TSNDecimal' to 'NSDecimalNumber'
E restkit.object_mapping:RKMappingOperation.m:441 Failed transformation of value at keyPath '(null)' to representation of type 'NSDecimalNumber': Error Domain=org.restkit.RKValueTransformers.ErrorDomain Code=3002 "Failed transformation of value '<TSNDecimal: 0x9652900> (entity: TSNDecimal; id: 0x9664220 <x-coredata:///TSNDecimal/tB2DF8887-7E6C-420F-998A-D250751E5CED165> ; data: {
number = 5;
}) ({
mapping = {
collectionIndex = 3221208359;
};
})' to NSDecimalNumber: none of the 2 value transformers consulted were successful." UserInfo=0x96bd900 {detailedErrors=(
"Error Domain=org.restkit.RKValueTransformers.ErrorDomain Code=3002 \"The given value is not already an instance of 'NSDecimalNumber'\" UserInfo=0x96bd630 {NSLocalizedDescription=The given value is not already an instance of 'NSDecimalNumber'}",
"Error Domain=org.restkit.RKValueTransformers.ErrorDomain Code=3000 \"Expected an `inputValue` of type `NSNull`, but got a `TSNDecimal`.\" UserInfo=0x96bd720 {NSLocalizedDescription=Expected an `inputValue` of type `NSNull`, but got a `TSNDecimal`.}"
), NSLocalizedDescription=Failed transformation of value '<TSNDecimal: 0x9652900> (entity: TSNDecimal; id: 0x9664220 <x-coredata:///TSNDecimal/tB2DF8887-7E6C-420F-998A-D250751E5CED165> ; data: {
number = 5;
}) ({
mapping = {
collectionIndex = 3221208359;
};
})' to NSDecimalNumber: none of the 2 value transformers consulted were successful.}
T restkit.object_mapping:RKMappingOperation.m:519 Did not find mappable attribute value keyPath '(null)'
D restkit.object_mapping:RKMappingOperation.m:905 Mapping operation did not find any mappable values for the attribute and relationship mappings in the given object representation
D restkit.object_mapping:RKMappingOperation.m:927 Failed mapping operation: No mappable values found for any of the attributes or relationship mappings
W restkit.object_mapping:RKMappingOperation.m:553 WARNING: Failed mapping nested object: No mappable values found for any of the attributes or relationship mappings
调试器在中显示这些映射 - (BOOL)mapOneToManyRelationshipWithValue:mapping:
(lldb) po relationshipMapping
<RKRelationshipMapping: 0x93d8330 amount => amount>
(lldb) po relationshipMapping.mapping
<RKEntityMapping:0x93b7d50 objectClass=TSNDecimal propertyMappings=
(
"<RKAttributeMapping: 0x93b8e60 (null) => number>"
)>
我注意到当TSNDecimal被序列化时(或者在映射过程之前),它再次在RKMappingOperation.m中创建,在 - (id)destinationObjectForMappingRepresentation:parentRepresentation:withMapping:inRelationship: on line
return [self.dataSource mappingOperation:self targetObjectForRepre ...
使用错误的构造函数 new (这就是为什么我在日志中看到coredata错误: CoreData:错误:无法在NSManagedObject类上调用指定的初始化程序)。 self.dataSource调用错误的mappingOperation:targetObjectForRepresentation:因为它是非托管对象的数据源(RKObjectMappingOperationDataSource)。它应该是RKManagedObjectMappingOperationDataSource。
我猜测它可能与RKObjectMapping诉RKEntityMapping问题有关。但是当我使用RKEntityMapping进行TSNTagAmountRequest时:
tagAmountRequestMapping = [RKEntityMapping mappingForEntityForName:[TSNTagAmountRequest class] inManagedObjectStore:managedObjectStore];
然后我收到错误:**由于未捕获的异常终止应用程序&#39; NSInvalidArgumentException&#39;,原因:&#39; RKRequestDescriptor
对象必须使用目标类为{{的映射进行初始化1}},得到了TSNTagAmountRequest&#39; (见NSMutableDictionary
)&#39; **
我已经更改了实现,因此它使用了反向映射:
[RKObjectMapping requestMapping]
在映射操作结束时使用异常输出JSON字典中的无效(非字符串)键:
RKObjectMapping* decimalMappingInverse = [(RKEntityMapping*)decimalMapping inverseMapping];
RKPropertyMapping* decimalPropertyMappingAmountInverse =
[RKRelationshipMapping relationshipMappingFromKeyPath:@"amount"
toKeyPath:@"amount"
withMapping:decimalMappingInverse];
[tagAmountRequestMapping addPropertyMapping:decimalPropertyMappingAmountInverse];
requestDescriptor = [RKRequestDescriptor requestDescriptorWithMapping:tagAmountRequestMapping
objectClass:[TSNTagAmountRequest class]
rootKeyPath:nil
method:RKRequestMethodPOST];
[_rkManager addRequestDescriptor:requestDescriptor];
日志:
(
{
5 = {
};
},
{
100 = {
};
}
)
除了上述异常外,结果与所需的身体不匹配{&#34;金额&#34;:[5,100]}:
D restkit.object_mapping:RKMappingOperation.m:860 Starting mapping operation...
T restkit.object_mapping:RKMappingOperation.m:861 Performing mapping operation: <RKMappingOperation 0xf844d50> for '__NSDictionaryM' object. Mapping values from object <TSNTicketAmountApiRequest: 0xf80e9b0> (entity: TSNTicketAmountApiRequest; id: 0xf86bbe0 <x-coredata:///TSNTicketAmountApiRequest/t5BFB6379-F8EB-4367-A53B-E1B3C531A34F66> ; data: {
amount = (
"0xf8c3b30 <x-coredata:///TSNDecimalApiTO/t5BFB6379-F8EB-4367-A53B-E1B3C531A34F67>",
"0xf80c370 <x-coredata:///TSNDecimalApiTO/t5BFB6379-F8EB-4367-A53B-E1B3C531A34F68>"
);
}) ((null)) to object {
} with object mapping (null)
T restkit.object_mapping:RKMappingOperation.m:454 Mapping attribute value keyPath 'token' to 'token'
T restkit.object_mapping:RKMappingOperation.m:470 Mapped attribute value from keyPath 'token' to 'token'. Value: SXppH1ajA9OspKHkQ6Uwi7dD7AoYVP7J:api
T restkit.object_mapping:RKMappingOperation.m:454 Mapping attribute value keyPath 'bonification' to 'bonification'
T restkit.object_mapping:RKMappingOperation.m:470 Mapped attribute value from keyPath 'bonification' to 'bonification'. Value: 1
D restkit.network:RKObjectParameterization.m:129 Serialized NSDecimalNumber value at keyPath to __NSCFString (1)
T restkit.object_mapping:RKMappingOperation.m:454 Mapping attribute value keyPath 'isNetCurrency' to 'isNetCurrency'
T restkit.object_mapping:RKMappingOperation.m:470 Mapped attribute value from keyPath 'isNetCurrency' to 'isNetCurrency'. Value: 0
D restkit.network:RKObjectParameterization.m:129 Serialized __NSCFNumber value at keyPath to __NSCFBoolean (0)
D restkit.object_mapping:RKMappingOperation.m:641 Mapping one to many relationship value at keyPath 'amount' to 'amount'
T restkit.object_mapping:RKMappingOperation.m:542 Performing nested object mapping using mapping <RKRelationshipMapping: 0xf87bf40 amount => amount> for data: <TSNDecimalApiTO: 0xf8f0a60> (entity: TSNDecimalApiTO; id: 0xf8c3b30 <x-coredata:///TSNDecimalApiTO/t5BFB6379-F8EB-4367-A53B-E1B3C531A34F67> ; data: {
number = 5;
})
D restkit.object_mapping:RKMappingOperation.m:860 Starting mapping operation...
T restkit.object_mapping:RKMappingOperation.m:861 Performing mapping operation: <RKMappingOperation 0x93779f0> for '__NSDictionaryM' object. Mapping values from object <TSNDecimalApiTO: 0xf8f0a60> (entity: TSNDecimalApiTO; id: 0xf8c3b30 <x-coredata:///TSNDecimalApiTO/t5BFB6379-F8EB-4367-A53B-E1B3C531A34F67> ; data: {
number = 5;
}) ({
mapping = {
collectionIndex = 3221208359;
};
}) to object {
} with object mapping (null)
T restkit.object_mapping:RKMappingOperation.m:439 Found transformable value at keyPath 'number'. Transforming from class 'NSDecimalNumber' to 'NSMutableDictionary'
T restkit.object_mapping:RKMappingOperation.m:454 Mapping attribute value keyPath 'number' to '(null)'
T restkit.object_mapping:RKMappingOperation.m:470 Mapped attribute value from keyPath 'number' to '(null)'. Value: {
5 = {
};
}
D restkit.object_mapping:RKMappingOperation.m:929 Finished mapping operation successfully...
T restkit.object_mapping:RKMappingOperation.m:542 Performing nested object mapping using mapping <RKRelationshipMapping: 0xf87bf40 amount => amount> for data: <TSNDecimalApiTO: 0xf8f0ea0> (entity: TSNDecimalApiTO; id: 0xf80c370 <x-coredata:///TSNDecimalApiTO/t5BFB6379-F8EB-4367-A53B-E1B3C531A34F68> ; data: {
number = 100;
})
D restkit.object_mapping:RKMappingOperation.m:860 Starting mapping operation...
T restkit.object_mapping:RKMappingOperation.m:861 Performing mapping operation: <RKMappingOperation 0x9311160> for '__NSDictionaryM' object. Mapping values from object <TSNDecimalApiTO: 0xf8f0ea0> (entity: TSNDecimalApiTO; id: 0xf80c370 <x-coredata:///TSNDecimalApiTO/t5BFB6379-F8EB-4367-A53B-E1B3C531A34F68> ; data: {
number = 100;
}) ({
mapping = {
collectionIndex = 3221208359;
};
}) to object {
} with object mapping (null)
T restkit.object_mapping:RKMappingOperation.m:439 Found transformable value at keyPath 'number'. Transforming from class 'NSDecimalNumber' to 'NSMutableDictionary'
T restkit.object_mapping:RKMappingOperation.m:454 Mapping attribute value keyPath 'number' to '(null)'
T restkit.object_mapping:RKMappingOperation.m:470 Mapped attribute value from keyPath 'number' to '(null)'. Value: {
};
}
D restkit.object_mapping:RKMappingOperation.m:929 Finished mapping operation successfully...
T restkit.object_mapping:RKMappingOperation.m:682 Mapped relationship object from keyPath 'amount' to 'amount'. Value: (
{
5 = {
};
},
{
100 = {
};
}
)
这个问题归结为如何将来自JSON的十进制数组数组解析为NSManagedObjects的NSSet(从第一时开始工作),反之亦然,从NSSet到JSON数组(非常令人沮丧,让它工作):
D restkit.object_mapping:RKMappingOperation.m:929 Finished mapping operation successfully...
exception Invalid (non-string) key in JSON dictionary
即
{"amount":[10,20,50]}
其中
TSNTagAmountRequest:{amount:[TSNDecimal, TSNDecimal, TSNDecimal, ...]}
和
@interface TSNTagAmountRequest : NSManagedObject
@property(nonatomic) NSSet *amount;
@end
其中
@interface TSNDecimal : NSManagedObject
@property(nonatomic) NSDecimalNumber* number; // is a helper property
@end
RKEntityMapping* tagAmountRequestMapping = [RKObjectMapping requestMapping];
[tagAmountRequestMapping
addPropertyMapping:decimalPropertyMappingAmountInverse];
其中
RKPropertyMapping* decimalPropertyMappingAmountInverse =
[RKRelationshipMapping
relationshipMappingFromKeyPath:@"amount"
toKeyPath:@"amount"
withMapping:decimalMappingInverse];
,其中
RKObjectMapping* decimalMappingInverse = [(RKEntityMapping*)decimalMapping inverseMapping];
方法+(NSData *)dataFromObject:error:来自RKNSJSONSerialization不能使用包含NSDictionary的映射中的结果对象:
RKObjectMapping* decimalMapping = [RKEntityMapping mappingForEntityForName:@"TSNDecimal" inManagedObjectStore:managedObjectStore];
[mapping addPropertyMapping:[RKAttributeMapping attributeMappingFromKeyPath:nil
toKeyPath:@"number"]];
requestDescriptor = [RKRequestDescriptor
requestDescriptorWithMapping:tagAmountRequestMapping
objectClass:[TSNTagAmountRequest class]
rootKeyPath:TSNServiceClientRemoteRootKeyPathNotNested
method:RKRequestMethodPOST];
[_rkManager addRequestDescriptor:requestDescriptor];
我期待像[5,100]这样的东西。
应用程序在JSON字典中使用无效(非字符串)键崩溃。
我不明白为什么[NSJSONSerialization dataWithJSONObject:object options:0 error:error];服务于这个奇怪的字典数组而不是NSDecimalNumbers数组。
我更改了TSNTagAmountRequest和TSNDecimal之间关系映射的定义,以便TSNDecimal(来自金额NSSet的项)中的值以其属性&#34; number&#34;传播。
(
{
5 = {
};
},
{
100 = {
};
}
)
Restkit引擎,来自RKMappingOperation.m的 applyRelationshipMappings 方法能够提取数值5,100,但最终JSON组装不正确:
RKPropertyMapping* decimalPropertyMappingAmountInverse =
[RKRelationshipMapping relationshipMappingFromKeyPath:@"amount.number"
toKeyPath:@"amount"
withMapping:decimalApiMappingInverse];
缺少值。我快到了。
在为所有涉及的实体设置inverseMapping后,输入请求描述符,仍然输出(由映射编号 - > nil驱动)与字典字典而不是JSON数组错误地组合在一起。唯一的方法是继承RKNSJSONSerialization并修复结构,即将字典字典翻译成与ns json序列化程序兼容的简单nsarray。