当前位置: 首页 > 知识库问答 >
问题:

对于将从JSON解析的对象模型的属性,我应该使用optional吗?

柴默
2023-03-14

我的 iOS 应用程序有一个非常常见的设置:它对使用JSON对象响应的API服务器进行HTTP查询。然后将这些JSON对象解析为适当的Swift对象。

最初,我将属性分为必需属性和可选属性,主要基于我的API服务器的数据库需求。例如,< code>id、< code>email和< code>name是必填字段,因此它们使用非可选类型。其他类型在数据库中可以是< code>NULL,因此它们是可选类型。

class User {
  let id: Int
  let email: String
  let profile: String?
  let name: String
  let motive: String?
  let address: String?
  let profilePhotoUrl: String?
}

最近,我开始怀疑这是否是一个好的设置。我发现,尽管一些财产可能始终存在于数据库中,但这并不意味着这些财产将始终包含在JSON响应中。

例如,在用户配置文件页面中,需要所有这些字段才能正确显示视图。因此,JSON响应将包含所有这些字段。然而,对于列出用户姓名的视图,我不需要emailid,JSON响应可能也不应该包含这些属性。不幸的是,这将导致错误并在将JSON响应解析为Swift对象时使应用程序崩溃,因为应用程序期望idemailname始终不是-nil。

我正在考虑将Swift对象的所有财产更改为可选的,但这感觉就像是放弃了这种特定于语言的特性的所有好处。此外,无论如何,我将不得不在应用程序的其他地方编写更多的代码行来展开所有这些选项。

另一方面,JSON对象本质上不太能与Swift的严格静态类型和零检查进行互操作,因此接受这种烦恼可能更好。

我是否应该过渡到将每个属性都作为选项的模型?还是有更好的方法?如有任何意见,我将不胜感激。

共有3个答案

奚晟
2023-03-14

前提:

部分表示是 REST 中的常见模式。这是否意味着 Swift 中的所有属性都需要是可选的?例如,客户端可能只需要视图的用户 ID 列表。这是否意味着所有其他属性(名称、电子邮件等)都需要标记为可选?这在 Swift 中是好的做法吗?

在模型中标记可选属性只能表明密钥可能会或可能不会出现。它允许读者在第一眼就知道模型的某些事情。
如果您只为不同的API响应结构维护一个通用模型并使所有属性可选,这是否是一个好的做法是非常有争议的。
我已经这样做了,它咬人。有时很好,有时只是不够清楚。

为多个API保留一个模型就像设计一个具有多个UI元素的ViewController,并根据具体情况确定应显示或不显示哪个UI元素
这增加了新开发人员的学习曲线,因为他们更了解所涉及的系统。

假设我们继续使用Swift的编码/解码模型的Codable,我会将其分解为单独的模型,而不是维护一个具有所有选项的通用模型

我做出决定的原因是:

> < li>

分离的清晰度

  • 每个模型都有特定的用途
  • 更干净的自定义解码器的范围
    • 当 json 结构需要一些预处理时很有用

    考虑稍后可能出现的API特定附加密钥。

      < li >如果这个用户列表API是唯一一个需要更多关键字的API,比如朋友数量或其他统计数据,该怎么办? < ul > < li >我是否应该继续加载单个模型以支持不同的情况,其中附加键只出现在一个API响应中,而不出现在另一个API响应中? < li >如果第三方API旨在获取用户信息,但这次的目的略有不同,该怎么办?我应该用更多的键重载同一个模型吗?

    但是,如果我很懒惰,并且我有一种强烈的感觉,疯狂的变化不会出现,我会继续将所有密钥设置为可选并承担相关费用。

欧阳博文
2023-03-14

首先要做的是问:“列出用户名称的视图”的元素

struct UserList: Decodable {

    struct Item: Decodable {
        var id: Int
        var name: String
    }

    var items: [Item]

}

(虽然问题说 JSON 响应可能不包含 id,但似乎没有 id 的用户列表并不是特别有用,所以我在这里要求它。

如果您真的希望它们是相同类型的对象,那么您可能希望将用户建模为具有服务器始终发送的核心财产和可能为零的“详细信息”字段:

class User: Decodable {
    let id: Int
    let name: String
    let details: Details?

    struct Details: Decodable {
        var email: String
        var profile: String?
        var motive: String?
        var address: String?
        var profilePhotoUrl: String?
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        id = try container.decode(Int.self, forKey: .id)
        name = try container.decode(String.self, forKey: .name)
        details = container.contains(.email) ? try Details(from: decoder) : nil
    }

    enum CodingKeys: String, CodingKey {
        case id
        case name

        case email // Used to detect presence of Details
    }
}

注意,我使用< code > Details(from:decoder)而不是通常的< code > container . decode(Details . self,forKey:。详情)。我使用< code > Details(from:decoder)来实现这一点,以便< code>Details的属性与< code>User的属性来自同一个JSON对象,而不需要嵌套对象。

董康平
2023-03-14

有三种方法可以做到这一点:

>

  • 始终发送所有JSON数据,并将您的属性设为非可选。

    将所有属性设为可选。

    使所有属性都非可选,并编写自己的 init(from:) 方法将默认值分配给缺失值,如本答案中所述。

    所有这些都应该有效;哪一个是“最好的”是基于意见的,因此超出了堆栈溢出答案的范围。根据您的特定需求选择最方便的一种。

  •  类似资料:
    • 我以前没有使用过JSON数据,因此问题来了。我在文件中有以下JSON对象。 这是我的模型对象。 我的任务是读取JSON对象并返回模型对象列表。 我已经导入了简单的。json系列jar,这是我读取文件的代码。 我的问题是, 如何将JSON文档解析为我的Model对象? 如果输入文件是JSON但格式不同,如何抛出异常/处理异常? 感谢任何帮助。

    • 问题内容: 我正在尝试从Python解析JSON。我最近开始使用Python,因此我跟随一些stackoverflow教程,了解如何使用Python解析JSON,并提出了以下代码- 但是,每当我运行上面的代码时,我总是会收到此错误- 有什么想法我在这里做错了吗?我在Windows中运行cygwin,仅从那里运行python程序。我正在使用Python 2.7.3 还有解析JSON的更好,有效的方法

    • 问题内容: 我正在编写一个使用Json API的库,并且在使用Gson作为解析库时遇到了设计问题。 如果一切顺利,则端点之一将返回对象: 但是,API中所有端点的错误模式都是json 而不是数组。 在POJO中对此建模时会出现问题。因为错误模式对于所有API端点都是通用的,所以我决定有一个仅映射errors属性的抽象类。 现在,我想继承自此,以获取“免费”错误映射和每个API端点响应的POJO。但

    • 问题内容: 我正在使用Java中的对象进行基本的HTTP身份验证。 我期待一个JSON对象,或者是有效JSON对象格式的字符串数据,或者是带有简单纯文本(即有效JSON)的HTML。返回响应后如何从中访问它? 问题答案: 您可以使用以下方法获取原始数据。顺便说一句,此模式适用于Java6。如果您使用的是Java 7或更高版本,请考虑try-with- resources模式 。 然后,您可以将返回

    • 本文向大家介绍JavaScript中Boolean对象的属性解析,包括了JavaScript中Boolean对象的属性解析的使用技巧和注意事项,需要的朋友参考一下 constructor 属性 实例 返回通过 myvar 对象的原型创建的函数: 结果输出: 定义和用法 constructor 属性返回对创建此对象的 Boolean 函数的引用。 prototype 构造器 为 Boolean 对象

    • 英文原文:http://emberjs.com/guides/object-model/computed-properties/ 什么是计算属性? 简单地来说,计算属性就是将函数声明为属性。通过定义一个如同函数一般的计算属性,Ember将会自动调用该函数来获取计算属性的值,此后就可以如同使用普通静态属性一样来使用计算属性。 在需要使用一个或者多个属性的变形,或者手动修改其数据的时候非常有用。 计算

    • 问题内容: 我想在REST应用程序中接受和响应JSON对象。我需要发送和接收的数据在.properties文件中。我已经阅读了它们,现在位于Object(From )中。是否可以在不实现新类的情况下编组和解组对象? 我在Weblogic服务器中使用Jax-rs API。 问题答案: 对WebLogic不太熟悉,因此我不知道它使用的是哪个版本的Jersey(1.x或2.x),但是使用1.x,您可以简

    • 我想由jackson将json更改为object,对象包含类型字段。 例外情况: 豆子: 我提供了setter/getter和字段can的一一映射。我使用的将json更改为object。