简体   繁体   English

将 JSON 解析为 Objective C 中的预定义类

[英]Parsing JSON to a predefined class in Objective C

I have a json string like:我有一个 json 字符串,如:

{
  "a":"val1",
  "b":"val2",
  "c":"val3"
}

And I have an objective C header file like:我有一个客观的 C 头文件,如:

@interface TestItem : NSObject

@property NSString *a;
@property NSString *b;
@property NSString *c;

@end

Can I parse the Json and get an instance of TestItem Class?我可以解析 Json 并获取 TestItem 类的实例吗?

I know how to parse the json into a dictionary, but I want to parse it in a class (similar to what gson does in Java).我知道如何将json解析成字典,但我想在一个类中解析它(类似于gson在Java中所做的)。

Instead of using dictionaries directly you can always deserialize (parse) JSON to your class with using Key-value coding.您始终可以使用键值编码将 JSON 反序列化(解析)到您的类,而不是直接使用字典。 Key-value coding is a great feature of Cocoa that lets you access properties and instance variables of class at runtime by name.键值编码是 Cocoa 的一个很棒的特性,它允许您在运行时通过名称访问类的属性和实例变量。 As I can see your JSON model is not complex and you can apply this easily.正如我所看到的,您的 JSON 模型并不复杂,您可以轻松应用它。

person.h人.h

#import <Foundation/Foundation.h>

@interface Person : NSObject

@property NSString *personName;
@property NSString *personMiddleName;
@property NSString *personLastname;

- (instancetype)initWithJSONString:(NSString *)JSONString;

@end

person.m人.m

#import "Person.h"

@implementation Person

- (instancetype)init
{
    self = [super init];
    if (self) {

    }
    return self;
}

- (instancetype)initWithJSONString:(NSString *)JSONString
{
    self = [super init];
    if (self) {

        NSError *error = nil;
        NSData *JSONData = [JSONString dataUsingEncoding:NSUTF8StringEncoding];
        NSDictionary *JSONDictionary = [NSJSONSerialization JSONObjectWithData:JSONData options:0 error:&error];

        if (!error && JSONDictionary) {

            //Loop method
            for (NSString* key in JSONDictionary) {
                [self setValue:[JSONDictionary valueForKey:key] forKey:key];
            }
            // Instead of Loop method you can also use:
            // thanks @sapi for good catch and warning.
            // [self setValuesForKeysWithDictionary:JSONDictionary];
        }
    }
    return self;
}

@end

appDelegate.m appDelegate.m

@implementation AppDelegate

    - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {

        // JSON String
        NSString *JSONStr = @"{ \"personName\":\"MyName\", \"personMiddleName\":\"MyMiddleName\", \"personLastname\":\"MyLastName\" }";

        // Init custom class 
        Person *person = [[Person alloc] initWithJSONString:JSONStr];

        // Here we can print out all of custom object properties. 
        NSLog(@"%@", person.personName); //Print MyName 
        NSLog(@"%@", person.personMiddleName); //Print MyMiddleName
        NSLog(@"%@", person.personLastname); //Print MyLastName    
    }

@end

The article using JSON to load Objective-C objects good point to start.这篇使用 JSON 加载 Objective-C 对象的文章很好地开始。

We can automatically map response json in our model classes with the help of third party library我们可以在第三方库的帮助下在我们的模型类中自动映射响应 json

JSONMode https://github.com/mattiaslevin/ObjectMapper JSONMode https://github.com/mattiaslevin/ObjectMapper

Simply create your class like below define your data model properties.只需创建您的类,如下所示定义您的数据模型属性。 Be careful the keys of your json response should be same as the property you are defining.请注意 json 响应的键应与您定义的属性相同。 You will get more clear picture below because I am sharing my json response with the structure of the model classes -您将在下面获得更清晰的图片,因为我正在与模型类的结构共享我的 json 响应 -

Response json响应 json

{
    "code": 200,
    "data": [
        {
            "stockName": "sh000001",
            "category": "china",
            "stockStatus": "open",
            "roadMap": [
                {
                    "stockTimeStamp": "10:25",
                    "stockValue": "2789.915",
                    "number1": 1,
                    "number2": 5
                },
                {
                    "stockTimeStamp": "10:30",
                    "stockValue": "2790.153",
                    "number1": 5,
                    "number2": 3
                }
            ],
            "gameData": [
                {
                    "gameUUID": "e4fcd001-2499-45c3-a21c-d573b9e378cc",
                    "gameStatus": "Open"
                }
            ]
        },
        {
            "stockName": "usindex",
            "category": "usa",
            "stockStatus": "open",
            "roadMap": [
                {
                    "stockTimeStamp": "10:20",
                    "stockValue": "100.1020",
                    "number1": 2,
                    "number2": 0
                },
                {
                    "stockTimeStamp": "10:25",
                    "stockValue": "100.0958",
                    "number1": 5,
                    "number2": 8
                }
            ],
            "gameData": [
                {
                    "gameUUID": "1a6c9889-41e9-410a-a409-e10126ffeeb5",
                    "gameStatus": "Open"
                }
            ]
        },
        {
            "stockName": "btc1",
            "category": "crypto",
            "stockStatus": "open",
            "roadMap": [
                {
                    "stockTimeStamp": "02:26",
                    "stockValue": "7670.00",
                    "number1": 0,
                    "number2": 0
                },
                {
                    "stockTimeStamp": "02:25",
                    "stockValue": "7670.00",
                    "number1": 0,
                    "number2": 0
                }
            ],
            "gameData": [
                {
                    "gameUUID": "40526121-f199-4649-b169-9913bd883186",
                    "gameStatus": "Open"
                }
            ]
        }
    ],
    "status": true,
    "message": [
        "success"
    ]
}

YourModel.h file你的Model.h文件

#import "JSONModel.h"

@interface RoadmapElementModel : JSONModel
@property (nonatomic) NSInteger number1;
@property (nonatomic) NSInteger number2;
@property (nonatomic) NSString *stockTimeStamp;
@property (nonatomic) NSString *stockValue;
@end

@interface RoadmapDataModel : JSONModel
@property (nonatomic) NSString *stockName;
@property (nonatomic) NSString *category;
@property (nonatomic) NSString *stockStatus;
@property (nonatomic) NSArray <RoadmapElementModel *> *roadMap;
@end

@interface RoadMapModel : JSONModel
@property (nonatomic) NSInteger code;
@property (nonatomic) BOOL status;
@property (nonatomic) NSArray<RoadmapDataModel *>*data;
@property (nonatomic) NSArray<NSString *> *message;
@end

Note:- You do not need to write anything to your YourModel.h file.注意:-您无需在YourModel.h文件中写入任何内容。

Now just write below code after getting the response JsonString in your ViewController class现在只需在您的 ViewController 类中获得响应 JsonString 后编写下面的代码

NSError *error;
RoadMapModel *roadmap = [[RoadMapModel alloc] initWithString:myString error:&error];
- (id)initWithDictionary:(NSDictionary *)dictionary {
    if (self = [super init]) {
        _a = [dictionary objectForKey:@"a"];
        _b = [dictionary objectForKey:@"b"];
        _c = [dictionary objectForKey:@"c"];
    }
    return self;
}

You have two solutions:您有两种解决方案:

Manual手动的

Write code to parse the JSON to a dictionary and after populate manually an instance of your target object编写代码将 JSON 解析为字典,然后手动填充目标对象的实例

NSDictionary *jsonDictionary = //JSON parser

TestItem *ti = [TestItem new];
ti.a = [jsonDictionary objectForKey:@"a"];
ti.b = [jsonDictionary objectForKey:@"b"];
ti.c = [jsonDictionary objectForKey:@"c"];

iOS provides you a json parser. iOS 为您提供了一个 json 解析器。 Look at this reply for more infos How do I deserialize a JSON string into an NSDictionary?查看此回复以获取更多信息如何将 JSON 字符串反序列化为 NSDictionary? (For iOS 5+) (适用于 iOS 5+)

(you should also check that the objects type match your expectations and eventually manage properly cases of error) (您还应该检查对象类型是否符合您的期望并最终正确管理错误情况)

Mapping lib映射库

Use a mapper library like JTObjectMapping that can help you to define how your object should be filled using the JSON.使用像JTObjectMapping这样的映射器库,它可以帮助您定义如何使用 JSON 填充对象。 Usually I prefer this solution.通常我更喜欢这个解决方案。 It automatically checks for types and your code will be clearer.它会自动检查类型,您的代码会更清晰。

Use OCMapper to automate your mapping.使用 OCMapper 自动化您的映射。 it has the ability to automatically map all fields, and simple to use.它具有自动映射所有字段的能力,并且使用简单。

https://github.com/aryaxt/OCMapper https://github.com/aryaxt/OCMapper

let request = Manager.sharedInstance.request(requestWithPath("example.com/users/5", method: .GET, parameters: nil))

request.responseObject(User.self) { request, response, user, error in
    println(user.firstName)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM