Json 解码总是返回 nil

Json decode always return nil

提问人:Seb 提问时间:10/26/2023 最后编辑:Joakim DanielsonSeb 更新时间:10/26/2023 访问量:103

问:

我创建了一个 swiftui 应用程序,但出于测试目的,我创建了一个模拟的存储库来从 json 返回数据,而不是进行 api 调用。的结果总是零...JSONDecode

Json 如下,存储在根项目(如 google.plist、ContentView 等)中。

[
    {
        "ts": 1000000,
        "id": 1,
        "userName": "honeybee",
        "userLocation": "Honey bee",
        "userImageUrl": "user_1",
        "title": "Here",
        "postType": "post",
        "postImageUrl": "food_1",
    },
    {
        "ts": 1000000,
        "id": 2,
        "userName": "honeybee",
        "userLocation": "Honey bee",
        "userImageUrl": "user_2",
        "title": "Here",
        "postType": "store",
        "postImageUrl": "food_2"
    },

我创建了一个模型,如下所示:FeedItemEntity

enum PostType: String, Codable {
    case Post =  "post"
    case Store = "store"
    case Restaurant = "restaurant"
    case Review = "review"
    case Recipe = "recipe"
}

struct FeedItemEntity: Codable {
    var ts: Int
    var userName: String
    var userLocation: String
    var userImageUrl: String
    var title: String
    var postImageUrl: String
    var postType: PostType
    var rating: Int
}

extension FeedItemEntity: Identifiable {
    var id: UUID {
        let id = UUID()
        return id
    }
}

然后我的代码正在这样做:

class MockedFeedService: FeedServiceProtocol {
    
    static let shared = MockedFeedService()

    
    func getFeed() -> Future<[ios_foodloose_app.FeedItemEntity], Error> {
        return Future<[FeedItemEntity], Error> { promise in
            
            guard let url = Bundle(for: MockedFeedService.self).url(forResource: "basic-test-feed-response",withExtension: "json"),
                  let data = try? Data(contentsOf: url) else {
                return promise(.failure(NSError(domain: "", code: 401, userInfo: [ NSLocalizedDescriptionKey: "Error"])))
            }
            
            let response = try? JSONDecoder().decode( [FeedItemEntity].self, from: data)
            promise(.success(response!))
        }
    }
    
} 

就我而言,总是responsenil

知道为什么吗?

谢谢

JSON 斯威夫特

评论

2赞 vadian 10/26/2023
在块中替换为并打印 .这是毫无意义的。解码 JSON 是同步的。try?trydo catcherrorFuture
1赞 Joakim Danielson 10/26/2023
另一个使用...我没有尝试过你的代码,但你有,在你的 json 中,但你的自定义类型实现了自己的逻辑。这看起来有点可疑。try?idid
0赞 workingdog support Ukraine 10/26/2023
注意细节,除了所有其他注释外,你的 json 中没有。使用评论建议重试。rating

答:

0赞 Nick 10/26/2023 #1

您的 JSON 文件不包含字段。rating

您可以通过向数组的所有项目添加字段来更新您的,或者在模型中设置可选字段,如下所示:basic-test-feed-response.jsonratingratingFeedItemEntity

struct FeedItemEntity: Codable {
    var ts: Int
    var userName: String
    var userLocation: String
    var userImageUrl: String
    var title: String
    var postImageUrl: String
    var postType: PostType
    var rating: Int?
}

您可以使用机制来获取出错的描述:do-catch

do {
    let response = try JSONDecoder().decode([FeedItemEntity].self, from: data)
    promise(.success(response))
} catch {
    print(error)
}

在 Xcode 控制台中,你将看到:

keyNotFound(CodingKeys(stringValue: “rating”, intValue: nil), Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: “索引 0“, intValue: 0)], debugDescription: ”没有与键关联的值 CodingKeys(stringValue: “rating”, intValue: nil) (“rating”).“, underlyingError: nil))

0赞 Narendar Singh Saini 10/26/2023 #2

这将起作用,我在JSON和解码器中进行了一些调整。请根据您的需要进行修改。

import Foundation

let json = """
[
    {
        "ts": 1000000,
        "id": 1,
        "userName": "honeybee",
        "userLocation": "Honey bee",
        "userImageUrl": "user_1",
        "title": "Here",
        "postType": "post",
        "postImageUrl": "food_1"
    },
    {
        "ts": 1000000,
        "id": 2,
        "userName": "honeybee",
        "userLocation": "Honey bee",
        "userImageUrl": "user_2",
        "title": "Here",
        "postType": "store",
        "postImageUrl": "food_2"
    }
]
""".data(using: .utf8)!
print (json)

enum PostType: String, Codable {
    case Post =  "post"
    case Store = "store"
    case Restaurant = "restaurant"
    case Review = "review"
    case Recipe = "recipe"
}

struct FeedItemEntity: Codable {
    var ts: Int
    var userName: String
    var userLocation: String
    var userImageUrl: String
    var title: String
    var postImageUrl: String
    var postType: PostType
}

extension FeedItemEntity: Identifiable {
    var id: String {
        let id = UUID().uuidString
        return id
    }
}

// create a JSON decoder
let decoder = JSONDecoder()

// decode the JSON into your model object and print the result
do {
    let feed = try decoder.decode([FeedItemEntity].self, from: json)
    print(feed)
} catch {
    print(error)
}