Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FileManager jsonFromFile only support json dictionary #845

Open
tospery opened this issue May 18, 2020 · 3 comments
Open

FileManager jsonFromFile only support json dictionary #845

tospery opened this issue May 18, 2020 · 3 comments

Comments

@tospery
Copy link

tospery commented May 18, 2020

FileManager.jsonFromFile extension do not support JSON array
e.g.

[ 
  {
   ... 
  }
]
@LucianoPAlmeida LucianoPAlmeida changed the title jsonFromFile only support json dictionary FileManager jsonFromFile only support json dictionary May 18, 2020
@LucianoPAlmeida
Copy link
Member

Thanks for reporting @tospery

@cHaLkdusT
Copy link
Member

The problem is because of downcasting of the returned value.

Do we want to create another API that returns [[String: Any]] or refactor the existing API to return Any?, and let the caller to handle if they wanted to cast it to Dictionary or Array of Dictionaries instead?

@guykogus
Copy link
Contributor

If we change the current API to return Any?, which would involve no casting, it'd be a breaking change, unfortunately. The current return type is completely wrong anyway, considering that the default parameter for readingOptions is .allowFragments, which would actually return nil if it was one.

I think the current functions should be deprecated and replaced with a new function returning Any?.

Alongside it I wouldn't mind having the same function for reading/writing. I actually have the following FileManager extensions in my projects (could use a little touch up, probably):

extension FileManager {
    enum FileError: LocalizedError {
        case failedToSave(path: String)
        case failedToLoad(path: String)

        var errorDescription: String? {
            switch self {
            case .failedToSave(let path):
                return "Failed to save file to path \(path)"
            case .failedToLoad(let path):
                return "Failed to save file to path \(path)"
            }
        }
    }

    func saveToJSON<T: Encodable>(_ object: T?,
                                  at url: URL,
                                  attributes: [FileAttributeKey: Any]? = nil) throws {
        guard let object = object else {
            if fileExists(atPath: url.path) {
                try removeItem(at: url)
            }
            return
        }

        let documentURL = url.deletingLastPathComponent()
        if !fileExists(atPath: documentURL.path) {
            try createDirectory(at: documentURL, withIntermediateDirectories: true, attributes: attributes)
        }

        let encoder = JSONEncoder()
        let data = try encoder.encode(object)
        let path = url.path
        guard createFile(atPath: path,
                         contents: data,
                         attributes: attributes) else {
                            throw FileError.failedToSave(path: path)
        }
    }

    func loadFromJSON<T: Decodable>(at url: URL) throws -> T? {
        guard fileExists(atPath: url.path) else { return nil }

        let decoder = JSONDecoder()
        let path = url.path
        guard let data = contents(atPath: path) else {
            throw FileError.failedToLoad(path: path)
        }
        return try decoder.decode(T.self, from: data)
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants