0

I would like to ask you some help again. This time I'm struggling with ObservableObject. My main goal is to have a single json parser in a single file which would work for all kind of models.

So.. I want to pass a model name and a file name as arguments to a method declared as ObservableObject.

public class JsonParser: ObservableObject {
@Published var result = [articleModel]()

init() {
    load(jsonFileName: "words")
}

I would like to call it like that:

@ObservedObject var myResult = JsonParser(jsonFile: "words", model: "articleModel")

The problem is.. I do not know how to pass the model and the file name as arguments in this specific SwiftUI framework. If somebody could give me some hints, I would appreciate that a lot.

4
  • So you want articleModel to be the type of objects in the result array? That's not possible in Swift, types need to be known at compile time, there no dynamic typing. Commented Apr 17, 2020 at 13:22
  • Correct, that is exactly what I wanted to do. Hmm. What shall I do then? I would like to minimise the amount of methods & files in my project by using a single parser. Commented Apr 17, 2020 at 13:25
  • You need to use generics if you know the types in compile time. Just a note: your question has nothing to do with SwiftUI, so I removed the tag - the fact that your type is an ObservableObject doesn't change anything related to your actual problem. Commented Apr 17, 2020 at 13:34
  • 1
    What kind of model do you have in mind here? (JSONDecoder is already a system for parsing all kinds of models, so it's not quite clear where you're having trouble.) What code have you written already that is getting duplicated? When you have existing duplication, it is much easier to explore how to remove that duplication. There's no one kind of code that would be appropriate for every conceivable kind of model, so it matters what kinds of problems you're trying to solve. It's also not clear in what way this is supposed to be observable. How are changes tied to the JSON? Does it sync? Commented Apr 17, 2020 at 13:49

2 Answers 2

1

If you want to create a JSON parse that can handle different types of input, make it a generic type.

public class JsonParser<Object>: ObservableObject {
    @Published var result: [Object]

    init(fileName: String) {
        result = Self.loadJson(file: fileName)
    }

    static func loadJson(file: String) -> [Object] {
        return [] // replace with your real implementation
    }
}

And initialise it like (assuming you have a model called City parsed from cities.json).

let citiesParser = JsonParser<City>(fileName: "cities.json")
Sign up to request clarification or add additional context in comments.

Comments

1

not 100% sure what you are asking, but to pass the model name and file as arguments, use this:

public class JsonParser: ObservableObject {

@Published var result = [String]()

init(jsonFile: String, model: String) {
    self.result.append(model)  // or whatever you want to do
    load(jsonFileName: jsonFile)
}
}

2 Comments

First of all, thank you for your answer. Yep, now it makes sense how to pass a file name inside the init() method (solution for passing a file name, is acceptable), however array type needs to be dynamic (it should depend on my model structure), any ideas how to resolve it?
In situations like this, I often rely on using protocol, use it just like a type in your array.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.