Ios 如何使用Mantle在JSON字典中省略空值?
我的模型继承自MTLModel(使用GitHub Mantle pod)。 MyModel.hIos 如何使用Mantle在JSON字典中省略空值?,ios,github-mantle,Ios,Github Mantle,我的模型继承自MTLModel(使用GitHub Mantle pod)。 MyModel.h #import <Mantle/Mantle.h> @interface MyModel : MTLModel <MTLJSONSerializing> @property (nonatomic, copy, readonly) NSString *UUID; @property (nonatomic, copy) NSString *someProp; @property (
#import <Mantle/Mantle.h>
@interface MyModel : MTLModel <MTLJSONSerializing>
@property (nonatomic, copy, readonly) NSString *UUID;
@property (nonatomic, copy) NSString *someProp;
@property (nonatomic, copy) NSString *anotherProp;
@end
现在我想使用AFNetworking将JSON发送到后端。在此之前,我将模型实例转换为JSON NSDictionary,用作请求中的参数/正文负载
NSDictionary *JSON = [MTLJSONAdapter JSONDictionaryFromModel:myModel];
但是这个JSON由奇怪的“”字符串组成,这些字符串表示我的模型的属性为零。相反,我希望Mantle忽略这些键/值对,只输出一个属性不是nil或NSNull.null的JSON,不管怎样。这是Mantle的一个常见问题,称为隐式JSON映射
MTLJSONAdapter
读取模型的所有属性,创建一个JSON字符串,可选地将属性名称替换为+JSONKeyPathsByPropertyKey
中给出的属性名称
如果希望从模型的JSON表示中排除某些属性,请将它们映射到+JSONKeyPathsByPropertyKey
中的NSNull.null
:
+ (NSDictionary *)JSONKeyPathsByPropertyKey {
return @{
@"UUID": @"id",
@"someProp": @"some_prop",
@"anotherProp": @"another",
@"myInternalProperty": NSNull.null,
@"myAnotherInternalProperty": NSNull.null,
};
}
隐式JSON映射最近已成为一个值得注意的问题,解决方案目前正在GitHub Mantle的主存储库中讨论 请参阅下的问题和当前讨论
编辑:我显然误解了这个问题,但现在,当我认为我理解正确时,答案很简单
MTLJSONAdapter
使用MTLModel
的dictionaryValue
属性生成JSON数据。如果希望从JSON本身中排除属性,可以在MYModel
中覆盖该方法:
- (NSDictionary *)dictionaryValue {
NSMutableDictionary *originalDictionaryValue = [[super dictionaryValue] mutableCopy];
if (self.aPropertyThatShouldBeExcludedWhenNil == nil) {
[originalDictionaryValue removeObjectForKey:@"aPropertyThatShouldBeExcludedWhenNil"];
}
/* repeat the process for other "hidden" properties */
return originalDictionaryValue;
}
编辑#2:检查代码*以删除所有
nil
:
- (NSDictionary *)dictionaryValue {
NSMutableDictionary *modifiedDictionaryValue = [[super dictionaryValue] mutableCopy];
for (NSString *originalKey in [super dictionaryValue]) {
if ([self valueForKey:originalKey] == nil) {
[modifiedDictionaryValue removeObjectForKey:originalKey];
}
}
return [modifiedDictionaryValue copy];
}
*-matths建议的代码示例。
编辑#2用于我使用以前的Mantle代码库。现在,我必须执行以下操作才能继续使用EDIT#2:
在文件MTLJSONAdapter.m中,替换此行:
NSDictionary *dictionaryValue = [model.dictionaryValue dictionaryWithValuesForKeys:propertyKeysToSerialize.allObjects];
与
以上是我目前的解决办法,以获得
{ }
而不是
{
"AddressLine2" : null,
"City" : null,
"ZipCode" : null,
"State" : null,
"AddressLine1" : null
}
我通过创建一个MTLJSONAdapter子类,并重写
-serializablePropertyKeys:forModel:
方法来删除无值键
MTLJSONADAPTER不带零。h
MTLJSONADAPTER不带零。m
重写-字典值没有给我预期的行为 所以我为MTL基类创建了一个方法
- (NSDictionary *)nonNullDictionaryWithAdditionalParams:(NSDictionary *)params error:(NSError *)error {
NSDictionary *allParams = [MTLJSONAdapter JSONDictionaryFromModel:self error: &error];
NSMutableDictionary *modifiedDictionaryValue = [allParams mutableCopy];
for (NSString *originalKey in allParams) {
if ([allParams objectForKey:originalKey] == NSNull.null) {
[modifiedDictionaryValue removeObjectForKey:originalKey];
}
}
[modifiedDictionaryValue addEntriesFromDictionary:params];
return [modifiedDictionaryValue copy];
}
你能发布MyModel的完整代码吗?我编辑了这个问题。因此,想象一个不完全RESTful的API。因此,在获取该模型的数据时,“some_prop”不会被传递,这将导致为零。将此模型转换回JSON时,属性将转换为“some_prop”:“”:(谢谢你的回答。我已经意识到在模型的JSON表示中排除了一些属性。但这不是一个在运行时忽略空值的解决方案,当它们为空时,但如果它们具有有效值,则包括它们。好吧,似乎我误解了这个问题。我编辑了我的答案,希望现在它将解决您的问题。;)很高兴它能工作!我添加了用于检查所有属性的代码示例,尽管我对其进行了一点改进。;)奇怪的是,编辑#2解决方案对我不起作用。dictionaryValue方法似乎从未被调用。我必须对每个可能为空的值使用值转换器。编辑#2过去对我有用。但现在最新的外套不起作用了。我看到的是类似“Address=”“;”的东西,而不是什么都没有。有人有更新的解决方案吗?谢谢!嗯,我认为您不应该直接修改Mantle framework中的文件。只有当您的属性名称与JSON密钥名称相同时,这才有意义
val
在[[NSNull null]isEqual:val]
中的val
是的,我忘记了,抱歉,编辑了。嗨@Hlung,你成功地使它适用于嵌套模型了吗?@SergiiN。我没有试过那个案子。这个解决方案行不通吗?
{
"AddressLine2" : null,
"City" : null,
"ZipCode" : null,
"State" : null,
"AddressLine1" : null
}
/** A MTLJSONAdapter subclass that removes model dictionaryValue keys whose value is `[NSNull null]`. */
@interface MTLJSONAdapterWithoutNil : MTLJSONAdapter
@end
#import "MTLJSONAdapterWithoutNil.h"
@implementation MTLJSONAdapterWithoutNil
- (NSSet *)serializablePropertyKeys:(NSSet *)propertyKeys forModel:(id<MTLJSONSerializing>)model {
NSMutableSet *ms = propertyKeys.mutableCopy;
NSDictionary *modelDictValue = [model dictionaryValue];
for (NSString *key in ms) {
id val = [modelDictValue valueForKey:key];
if ([[NSNull null] isEqual:val]) { // MTLModel -dictionaryValue nil value is represented by NSNull
[ms removeObject:key];
}
}
return [NSSet setWithSet:ms];
}
@end
+ (NSValueTransformer *)myDailyDataArrayJSONTransformer {
return [MTLJSONAdapterWithoutNil arrayTransformerWithModelClass:KBDailyData.class];
}
- (NSDictionary *)nonNullDictionaryWithAdditionalParams:(NSDictionary *)params error:(NSError *)error {
NSDictionary *allParams = [MTLJSONAdapter JSONDictionaryFromModel:self error: &error];
NSMutableDictionary *modifiedDictionaryValue = [allParams mutableCopy];
for (NSString *originalKey in allParams) {
if ([allParams objectForKey:originalKey] == NSNull.null) {
[modifiedDictionaryValue removeObjectForKey:originalKey];
}
}
[modifiedDictionaryValue addEntriesFromDictionary:params];
return [modifiedDictionaryValue copy];
}