ios github-mantle

ios - ¿Cómo omitir los valores nulos en el diccionario JSON usando Mantle?



github-mantle (4)

Tengo MyModel heredado de MTLModel (usando el pod GitHub Mantle). MyModel.h

#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

Ahora quiero enviar el JSON al backend usando AFNetworking. Antes de eso, convierto la instancia del modelo a un JSON NSDictionary para usar como parámetros / carga útil del cuerpo dentro de mi solicitud.

NSDictionary *JSON = [MTLJSONAdapter JSONDictionaryFromModel:myModel];

Pero este JSON consta de "" cadenas extrañas para las propiedades de mi modelo que son nulas. Lo que en cambio quiero es que Mantle omita estos pares clave / valor y solo escupa un JSON con solo las propiedades que no son nulas o NSNull.null, lo que sea.


Anulación: el diccionario de valores no me dio el comportamiento esperado

Así que creé un método para la clase Base 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]; }


El EDIT # 2 solía trabajar para mí con la base de código Mantle anterior. Ahora tengo que hacer lo siguiente para continuar usando EDIT # 2:

En el archivo MTLJSONAdapter.m, reemplace esta línea:

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

con

NSDictionary *dictionaryValue = model.dictionaryValue;

La anterior es mi actual solución para conseguir

{ }

en lugar de

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


Este es un problema común con Mantle y se denomina asignación JSON implícita .

MTLJSONAdapter lee todas las propiedades de un modelo para crear una cadena JSON que reemplaza opcionalmente los nombres de propiedad con los que se dan en +JSONKeyPathsByPropertyKey .

Si desea que algunas propiedades sean excluidas de la representación JSON de su modelo, NSNull.null a NSNull.null en su +JSONKeyPathsByPropertyKey :

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

El mapeo JSON implícito se ha convertido últimamente en un problema notable, una solución para la cual se está discutiendo actualmente en el repositorio de Mantle en GitHub.

Vea los temas #137 , #138 , #143 y la discusión actual en #149 .

EDIT: claramente entendí mal la pregunta, pero ahora, cuando supongo que la entiendo correctamente, la respuesta es simple.

MTLJSONAdapter genera los datos JSON usando la propiedad dictionaryValue MTLModel . Si desea excluir una propiedad del propio JSON, puede sobrescribir ese método en su MYModel :

- (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: verifique el código * para eliminar todos los valores que son 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.


Quito las claves de valor nulo al crear una subclase MTLJSONAdapter y al reemplazar -serializablePropertyKeys:forModel: method.

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

Y usa esto para crear el diccionario JSON en su lugar. Me gusta esto:

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

NOTA: si está anulando los métodos de NSValueTransformer para las propiedades de matriz o diccionario, también debe cambiar la clase MTLJSONAdapter a su subclase. Me gusta esto:

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