2013-09-23 40 views
16

Tôi có MyModel kế thừa từ MTLModel (sử dụng vỏ GitHub Mantle). MyModel.hLàm thế nào để bỏ qua các giá trị null trong Từ điển JSON bằng Mantle?

#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 

MyModel.m

#import "MyModel.h" 
@implementation MyModel 
+ (NSDictionary *)JSONKeyPathsByPropertyKey 
{ 
     return @{ 
      @"UUID": @"id", 
      @"someProp": @"some_prop", 
      @"anotherProp": @"another" 
    }; 
} 
} 
@end 

Bây giờ tôi muốn gửi JSON vào backend sử dụng AFNetworking. Trước đó, tôi chuyển đổi cá thể mô hình thành JSON NSDictionary để sử dụng như các tham số/tải trọng cơ thể trong yêu cầu của tôi.

NSDictionary *JSON = [MTLJSONAdapter JSONDictionaryFromModel:myModel]; 

Nhưng JSON này bao gồm các chuỗi "" lạ cho các thuộc tính của mô hình của tôi không có. Những gì tôi thay vì muốn là Mantle để bỏ qua các cặp khóa/giá trị này và chỉ nhổ ra một JSON với chỉ các thuộc tính không phải là nil hoặc NSNull.null, bất cứ điều gì.

+0

Bạn có thể gửi mã đầy đủ cho MyModel? –

+0

Tôi đã chỉnh sửa câu hỏi. Vì vậy, hãy tưởng tượng một API không hoàn toàn là RESTful. Vì vậy, khi tìm nạp dữ liệu của mô hình đó, "some_prop" sẽ không được phân phối, dẫn đến kết quả là không. Khi chuyển đổi mô hình này trở lại thành JSON, thuộc tính được dịch thành "some_prop": "" :( – matths

Trả lời

37

Đây là vấn đề thường gặp với Mantle và được gọi là ánh xạ JSON ẩn.

MTLJSONAdapter đọc tất cả thuộc tính của mô hình để tạo chuỗi JSON tùy ý thay thế tên thuộc tính bằng tên được nêu trong +JSONKeyPathsByPropertyKey.

Nếu bạn muốn có một số thuộc tính được loại trừ khỏi các đại diện JSON của mô hình của bạn, đồ chúng để NSNull.null trong +JSONKeyPathsByPropertyKey của bạn:

+ (NSDictionary *)JSONKeyPathsByPropertyKey { 
    return @{ 
     @"UUID": @"id", 
     @"someProp": @"some_prop", 
     @"anotherProp": @"another", 
     @"myInternalProperty": NSNull.null, 
     @"myAnotherInternalProperty": NSNull.null, 
    }; 
} 

Ánh xạ JSON ngầm đã gần đây trở thành một vấn đề đáng chú ý, một giải pháp hiện đang được thảo luận tại kho lưu trữ tại nhà của Mantle tại GitHub.

thấy vấn đề #137, #138, #143 và các cuộc thảo luận hiện dưới #149.


EDIT: tôi hiểu lầm rõ câu hỏi, nhưng bây giờ, khi tôi cho rằng tôi hiểu nó một cách chính xác, câu trả lời rất đơn giản.

MTLJSONAdapter tạo dữ liệu JSON bằng cách sử dụng thuộc tính dictionaryValue của MTLModel. Nếu bạn muốn loại trừ một tài sản từ JSON bản thân, bạn có thể ghi đè lên phương pháp mà trong MYModel của bạn:

- (NSDictionary *)dictionaryValue { 
    NSMutableDictionary *originalDictionaryValue = [[super dictionaryValue] mutableCopy]; 

    if (self.aPropertyThatShouldBeExcludedWhenNil == nil) { 
     [originalDictionaryValue removeObjectForKey:@"aPropertyThatShouldBeExcludedWhenNil"]; 
    } 

    /* repeat the process for other "hidden" properties */ 

    return originalDictionaryValue; 
} 

EDIT # 2: Kiểm tra mã * để loại bỏ tất cả các giá trị mà là 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]; 
} 

* - code sample suggested by matths.

+0

Cảm ơn câu trả lời đó Và tôi đã biết loại trừ một số thuộc tính này từ biểu diễn JSON của mô hình. Nhưng đây không phải là một giải pháp cho việc bỏ qua các giá trị null _at runtime_ khi chúng là null, nhưng kể cả chúng, nếu chúng có giá trị hợp lệ – matths

+0

OK, có vẻ như tôi đã hiểu sai câu hỏi. sẽ sửa vấn đề của bạn.;) – akashivskyy

+0

Điều đó nghe có vẻ thú vị và thực sự giống như một giải pháp. Tôi sẽ thử sáng mai (CET) trong văn phòng từ máy làm việc của tôi, và chấp nhận câu trả lời khi nó hoạt động. – matths

-1

EDIT # 2 được sử dụng để làm việc cho tôi với cơ sở mã Mantle trước đó. Bây giờ tôi phải làm như sau để tiếp tục sử dụng EDIT # 2:

Trong tệp MTLJSONAdapter.m, thay thế dòng này:

NSDictionary *dictionaryValue = [model.dictionaryValue dictionaryWithValuesForKeys:propertyKeysToSerialize.allObjects]; 

với

NSDictionary *dictionaryValue = model.dictionaryValue; 

Trên đây là cách giải quyết hiện tại của tôi để có được

{ } 

thay vì

{ 
    "AddressLine2" : null, 
    "City" : null, 
    "ZipCode" : null, 
    "State" : null, 
    "AddressLine1" : null 
} 
+0

Hmm, tôi không nghĩ bạn nên sửa đổi các tệp trong khuôn khổ Mantle trực tiếp. – Hlung

+0

Điều đó chỉ có ý nghĩa nếu tên thuộc tính của bạn giống hệt với tên khóa JSON –

1

tôi loại bỏ nil phím có giá trị bằng cách tạo một MTLJ SONAdapter phân lớp và ghi đè phương thức -serializablePropertyKeys:forModel:.

MTLJSONAdapterWithoutNil.h

/** A MTLJSONAdapter subclass that removes model dictionaryValue keys whose value is `[NSNull null]`. */ 
@interface MTLJSONAdapterWithoutNil : MTLJSONAdapter 
@end 

MTLJSONAdapterWithoutNil.m

#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 

Và sử dụng này để tạo từ điển JSON để thay thế. Như thế này:

NSDictionary *JSONDictionary = [MTLJSONAdapterWithoutNil JSONDictionaryFromModel:collection error:nil];

LƯU Ý:nếu bạn đang trọng NSValueTransformer phương pháp cho mảng hoặc từ điển tài sản, bạn cũng phải thay đổi lớp MTLJSONAdapter để phân lớp của bạn là tốt. Như thế này:

+ (NSValueTransformer *)myDailyDataArrayJSONTransformer { 
    return [MTLJSONAdapterWithoutNil arrayTransformerWithModelClass:KBDailyData.class]; 
} 
+0

'val' trong' [[NSNull null] isEqual: val] '? –

+1

có vẻ như bạn quên nói 'val = modelDictValue [key]' –

+0

Vâng, tôi quên điều đó, xin lỗi T_T. Đã chỉnh sửa. – Hlung

0

Overriding - dictionaryValues ​​đã không cho tôi hành vi mong đợi

Vì vậy, tôi đã tạo ra một phương pháp cho lớp MTL cơ sở

- (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]; 
    } 
Các vấn đề liên quan