gpt4 book ai didi

ios - 规范化 JSON,使等效对象具有相同的哈希值

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:40:17 25 4
gpt4 key购买 nike

我将 JSON 对象存储在数据库中。这些对象中的许多(也许是大多数)都是重复的,因此我想将它们键入 SHA 散列之类的对象,以避免创建不必要的额外记录。

问题是,在我想将它们写入数据库时​​,我不再拥有 JSON 字节——只有 NSJSONSerialization 返回的 Foundation 对象。因为 NSDictionary 不对键顺序做任何保证(即使它做了,我也不确定我从中获取数据的服务器),我不能确定 NSJSONSerialization 会在我每次调用它时以相同的顺序输出每个对象的字段。这意味着同一个对象可能有不同的摘要,这让我节省空间的尝试落空了。

是否有一个 Objective-C JSON 库确实总是为等效对象编写完全相同的 JSON,大概是在编写键之前对键进行排序?我的目标是 iOS 7,但这可能是基础级别的问题。

最佳答案

我没有尝试编写自己的 JSON 序列化程序,而是决定通过一些代理技巧来欺骗 Apple 做我想做的事情。

用法:

NSData * JSONData = [NSJSONSerialization dataWithJSONObject:[jsonObject objectWithSortedKeys] options:0 error:&error];

标题:

#import <Foundation/Foundation.h>

@interface NSObject (sortedKeys)

/// Returns a proxy for the object in which all dictionary keys, including those of child objects at any level, will always be enumerated in sorted order.
- (id)objectWithSortedKeys;

@end

代码:

#import "NSObject+sortedKeys.h"

/// A CbxSortedKeyWrapper intercepts calls to methods like -allKeys, -objectEnumerator, -enumerateKeysAndObjectsUsingBlock:, etc. and makes them enumerate a sorted array of keys, thus ensuring that keys are enumerated in a stable order. It also replaces objects returned by any other methods (including, say, -objectForKey: or -objectAtIndex:) with wrapped versions of those objects, thereby ensuring that child objects are similarly sorted. There are a lot of flaws in this approach, but it works well enough for NSJSONSerialization.
@interface CbxSortedKeyWrapper: NSProxy

+ (id)sortedKeyWrapperForObject:(id)object;

@end

@implementation NSObject (sortedKeys)

- (id)objectWithSortedKeys {
return [CbxSortedKeyWrapper sortedKeyWrapperForObject:self];
}

@end

@implementation CbxSortedKeyWrapper {
id _representedObject;
NSArray * _keys;
}


+ (id)sortedKeyWrapperForObject:(id)object {
if(!object) {
return nil;
}

CbxSortedKeyWrapper * wrapper = [self alloc];
wrapper->_representedObject = [object copy];

if([wrapper->_representedObject respondsToSelector:@selector(allKeys)]) {
wrapper->_keys = [[wrapper->_representedObject allKeys] sortedArrayUsingSelector:@selector(compare:)];
}

return wrapper;
}

- (NSMethodSignature*)methodSignatureForSelector:(SEL)aSelector {
return [_representedObject methodSignatureForSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation*)invocation {
[invocation invokeWithTarget:_representedObject];

BOOL returnsObject = invocation.methodSignature.methodReturnType[0] == '@';

if(returnsObject) {
__unsafe_unretained id out = nil;
[invocation getReturnValue:&out];

__unsafe_unretained id wrapper = [CbxSortedKeyWrapper sortedKeyWrapperForObject:out];
[invocation setReturnValue:&wrapper];
}
}

- (NSEnumerator *)keyEnumerator {
return [_keys objectEnumerator];
}

- (NSEnumerator *)objectEnumerator {
if(_keys) {
return [[self allValues] objectEnumerator];
}
else {
return [CbxSortedKeyWrapper sortedKeyWrapperForObject:[_representedObject objectEnumerator]];
}
}

- (NSArray *)allKeys {
return _keys;
}

- (NSArray *)allValues {
return [CbxSortedKeyWrapper sortedKeyWrapperForObject:[_representedObject objectsForKeys:_keys notFoundMarker:[NSNull null]]];
}

- (void)enumerateKeysAndObjectsUsingBlock:(void (^)(id key, id obj, BOOL *stop))block {
[_keys enumerateObjectsUsingBlock:^(id key, NSUInteger idx, BOOL *stop) {
id obj = [CbxSortedKeyWrapper sortedKeyWrapperForObject:_representedObject[key]];
block(key, obj, stop);
}];
}

- (void)enumerateKeysAndObjectsWithOptions:(NSEnumerationOptions)opts usingBlock:(void (^)(id key, id obj, BOOL *stop))block {
[_keys enumerateObjectsWithOptions:opts usingBlock:^(id key, NSUInteger idx, BOOL *stop) {
id obj = [CbxSortedKeyWrapper sortedKeyWrapperForObject:_representedObject[key]];
block(key, obj, stop);
}];
}

- (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block {
[_representedObject enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL * stop) {
block([CbxSortedKeyWrapper sortedKeyWrapperForObject:obj], idx, stop);
}];
}

- (void)enumerateObjectsWithOptions:(NSEnumerationOptions)opts usingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block {
[_representedObject enumerateObjectsWithOptions:opts usingBlock:^(id obj, NSUInteger idx, BOOL * stop) {
block([CbxSortedKeyWrapper sortedKeyWrapperForObject:obj], idx, stop);
}];
}

- (void)enumerateObjectsAtIndexes:(NSIndexSet *)indexSet options:(NSEnumerationOptions)opts usingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block {
[_representedObject enumerateObjectsAtIndexes:indexSet options:opts usingBlock:^(id obj, NSUInteger idx, BOOL * stop) {
block([CbxSortedKeyWrapper sortedKeyWrapperForObject:obj], idx, stop);
}];
}

- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(__unsafe_unretained id *)stackbuf count:(NSUInteger)len {
NSUInteger count = [_keys countByEnumeratingWithState:state objects:stackbuf count:len];
for(NSUInteger i = 0; i < count; i++) {
stackbuf[i] = [CbxSortedKeyWrapper sortedKeyWrapperForObject:stackbuf[i]];
}
return count;
}

@end

关于ios - 规范化 JSON,使等效对象具有相同的哈希值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21672923/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com