2

How do you create objects when beforehand you don't know all it's properties?

I want to create a framework which works with 2 files:

  1. Input JSON file: Your JSON objects in a JSON file.
  2. Mapping JSON file: The mapping for these JSON objects in a JSON file.

Let's say you receive the following input JSON Person:

{
    "name": "John Snow",
    "age": 18,
    "country_code": "UK"
}

And you receive another dynamic JSON mapping file which specifies how some properties should be mapped from the Persons JSON:

{
    "source_type": "country_code",
    "source_value": "UK",
    "destination_type": "country",
    "destination_value": "United Kingdom"
}

In this case I want to change the key "country_code" to "country" with the correct value. The Persons JSON has to be changed to:

{
    "name": "John Snow",
    "age": 18,
    "country": "United Kingdom",
}

I can't create a struct which conforms to Codable because the keys of the JSON can be changed from the mapping:

// This won't work.
struct Person: Codable {
    var name: String // can be deleted
    var age: Int // can be changed to dateOfBirth
    var country: String // can be changed to country_code or national_code
}

It's also possible that the mapping asks to combine certain keys to create new properties:

{
    "source_type": "name|age",
    "source_value": "John Snow|18",
    "destination_type": "nameAge",
    "destination_value": "John Snow is 18 years old."
}

This would result in the following JSON object:

{
    "name": "John Snow",
    "age": 18,
    "country": "United Kingdom",
    "nameAge": "John Snow is 18 years old."
}

As you can see the input JSON can be totally altered by the mapping. This means that you can't predefine your models.

How do you solve this problem in a generic way? I am not asking for the code but I'm curious about the theoretical solution on how to solve this. Currently I create wrappers around dictionaries but this is nearly the same as creating predefined models which take away the whole concept of the generic framework.

Perhaps I have to define some protocol/interface instead of actual implementations? Or work with Generics?

avregi
  • 117
  • 1
  • 6
  • How will you use this dynamic models in your app? – Anton Belousov May 22 '18 at 10:41
  • @AntonBelousov I have no idea. I thought that perhaps a protocol could help me out by defining helper functions combined with a generic object. I doubt that this framework is technically possible. – avregi May 22 '18 at 10:49
  • 3
    With such a dynamic JSON, you shouldn't be using `Codable`. The whole point of `Codable` is to provide safe parsing by static typing, but if your JSON is dynamic to such extent, you won't be able to provide all properties/types at compile time, so you won't be able to use `Codable`. However, if you don't even know the possible property names and types that your JSON can have at compile time, you shouldn't even use a concrete type, you should simply store the values in a `Dictionary` which fits the dynamic nature of your JSON. – Dávid Pásztor May 22 '18 at 11:32
  • @DávidPásztor That's a very nice and clear explanation and I fully agree with that approach although it would become a headache retrieving values from a generic dictionary. I guess this dictionary approach would also be the solution when the expected JSON object is always the same (Person) but with dynamic properties which are based on the mapping file? – avregi May 22 '18 at 11:36
  • 1
    As long as you are aware of all possible values and their types, you can use an actual type, you just have to create optional properties (for instance if a `Person` can have a date of birth, which is a `Date` or an age which is an `Int`, you can do `var dob:Date?` and `var age:Int?`), but if the properties and their types can change without your knowledge, then you'll have to use a `Dictionary`. – Dávid Pásztor May 22 '18 at 11:40
  • @DávidPásztor Sounds good. I'll use dictionaries because the properties are fully dynamic even on an expected type like Person. The best solution would be to create a wrapper around this dictionary with some helper functions for some basic operations. I wonder if it's possible to create an actual type like Person though where 90% of the properties are always static and put the remaining 10% of dynamic properties in a dictionary property of Person so you have 90% of the properties always exposed and the remaining through that dictionary .. although this seems dirty. – avregi May 22 '18 at 11:55
  • 1
    Sure, if most of the properties are static, it makes more sense to create an actual type containing all known properties as instance properties of a concrete type and store all dynamic properties in a `Dictionary`. – Dávid Pásztor May 22 '18 at 11:57
  • @DávidPásztor Thanks for your help - I now have some ideas on what's possible and what's not. Can you summarise your replies in a comment so I can mark it as accepted? – avregi May 22 '18 at 11:58

0 Answers0