我需要使用CoreData在本地将来自API调用的一些数据存储为JSON。
问题是,JSON对我来说太复杂了,无法在CoreData中处理。我将JSON作为带有4个密钥的Dictionary
,这4个密钥再次保留Dictionary
个,Dictionary
个Array
和{{1} }}的
现在,我真的不知道应该如何为这个要求设计实体和属性,但是我试图这样做,我做的是,我创建了一个实体(比如XYZ),这个实体有4个关系(一个一个到4个其他实体,这四个实体只是我在JSON文件中得到的四个Dictionary
。我将这些Dictionary
和Array
存储为可转换类型。这有点令人困惑,对吧?那么让我把JSON数据放在这里
Dictionary
我的方法是否正常还是需要纠正?或者我需要以完全不同的方式实现它。请帮帮我,谢谢
答案 0 :(得分:5)
问题是您正在尝试根据JSON的结构创建CoreData实体。您应该根据JSON表示的对象以及它们之间的关系来创建实体。
您的问题并没有真正提供有关数据模型意图的足够信息,以便我给您一个确切的答案,但很可能将这些数据存储为一堆可转换的词典并非如此。最好的答案。使用可转换属性意味着不能查询这些值,并且您没有明确的列表应该包含在这些词典中。这意味着每当您访问数据时,您将有大量if let
语句检查字典中的字符串类型值。相反,每个值都应映射到CoreData实体上的属性。
我要问的第一件事是,这些outerKey
词典是否代表我的基础对象的属性和值,或者每个outerKey
是否真的代表了自己的与根对象有关系的模型对象。如果它们是一个对象的属性,则只需阅读JSON
并将值映射到实体上的属性。如果没有,那么你应该创建多个实体并创建你当前正在做的关系,但是你应该为这些实体上的每个值创建属性。
对于嵌套数组和词典,您可能还想创建具有关系的其他实体。
请记住,您的CoreData模型应该反映对象及其相互关联的方式。除非JSON
恰好代表正确的结构,否则它不应只反映JSON
的结构。
示例强>
因为我不知道你的数据真正代表什么,这对你的应用程序来说可能不是一个完美的结构,但是假设你的JSON
意味着这就是我要来的实体用。
- RootEntity
- outerKey1: OuterKey1 // one to one
- outerKey2: OuterKey2 // one to one
- outerKey3: OuterKey3 // one to one
- outerKey4: OuterKey4 // one to one
- OuterKey1
- someKey: String
- disableAutoFill: Bool
- disableABC: Bool
- disableXYZ: Bool
- disableThis: Bool
- disableThat: Bool
- disableBla: Bool
- disableBlaBla: Bool
- disableBlaBlaBlaBla: Bool
- disableBlaBlaBlaBlaBlaBla: Bool
- OuterKey2
- someKey: [SomeKeyEntity] // one to many
- enabled: Bool
- SomeKeyEntity
- markPath: Bool
- title: String
- urlString: String
- OuterKey3
- gatewayIP: String
- gatewayPort: Int
- gatewayRoutingURLs: [String] // This can be a transformable `Array`, unless you think you will need to query based on this property later
- enabled: Bool
- OuterKey4
- someCategories: [SomeCategoriesEntity] // one to many
- defaultURL: String
- enabled: Bool
- exceptionURLs: [String] // This can be a transformable `Array`, unless you think you will need to query based on this property later
- filterURLs: [String] // This can be a transformable `Array`, unless you think you will need to query based on this property later
- filteringFlag: Bool
希望有所帮助!
答案 1 :(得分:1)
是的,你不想按照自己的方式去做,完全忽略了这一点。您可以消化所有这些并构建正确的对象模型,或者只是将JSON保存到文件系统,然后只需在需要时重新加载并从中获取所需的数据。 有各种基于JSON的解析器可以让你做以下事情:
BOOL autofillDisabled = [jsonFile boolFor:@"outerkey.disableAutoFill"];
这将直接使用JSON作为您的数据存储。如果你真的需要根据这些数据建立一个对象模型,祝你好运。
哈,j / k。我已经解决了这个问题的一种方法(虽然从来没有使用过这种随机形成的json。在你获得根字典,并对数据有所了解以及如何使用它之后,构建一个简单的对象级联系统来深入研究数据。例如,从这里开始:
@interface ParseOperation : NSObject
+ (void) updateObject:(id)object fromDictionary:(NSDictionary *)aDict;
@end
然后,您将继续创建每个对象的内容:
@implementation SomeOperation // Which is a subclass of ParseOperation
+ (void) updateObject:(SomeObject *)object fromDictionary:(NSDictionary *)aDict
{
object.caption = [ParseObject stringForTag:@"caption" in:aDict];
object.status = [ParseObject stringForTag:@"status" in:aDict];
object.event = [ParseObject stringForTag:@"event" in:aDict];
}
然后只需创建您的驱动程序机制:
identifier = [ParseOperation stringForTag:@"SomeObject" in:dict];
SomeObject * object = (SomeObject *)[self object:NSStringFromClass([SomeObject class]) withIdentifier:identifier];
object.identifier = identifier;
[SomeOperation updateObject:object fromDictionary:dict];
这样做的实用方法是,您可以轻松处理JSON的复杂性,例如:
id check = [aDict objectForKey:@"subArray"];
// This is a mapping file you create, replacing "subArray" with your object's key
NSString * objectKey = [mapping objectForKey:@"object"];
if([check isKindOfClass:[NSMutableArray class]])
{
NSArray * array = (NSArray *)check;
for(NSDictionary * dict in array)
{
NSString * identifier = [ParseOperation stringForTag:identifierKey in:dict];
ManagedObject * object = [self object:objectKey withIdentifier:identifier];
NSString * operation = [NSString stringWithFormat:@"%@Operation", objectKey];
Class operationClass = NSClassFromString(operation);
[operationClass updateObject:object fromDictionary:dict];
}
}
答案 2 :(得分:0)
我真的不知道它会对你有所帮助,但是为了存储这种复杂的数据我更喜欢使用KISS XML API保存基于XML的保存(它易于使用)并在需要时解析它
您的xml文件可能看起来像
<RootEntity>
<OuterKey1>
<someKey> String </someKey>
<disableAutoFill> Bool</disableAutoFill> //and so on
</OuterKey1>
<OuterKey2>
<someKey> String </someKey>
<disableAutoFill> Bool</disableAutoFill> //and so on
</OuterKey2>
</RootEntity>