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

Adding more info to Schema and JSONParser #5

Open
Sajjon opened this issue Feb 27, 2018 · 4 comments
Open

Adding more info to Schema and JSONParser #5

Sajjon opened this issue Feb 27, 2018 · 4 comments
Assignees

Comments

@Sajjon
Copy link

Sajjon commented Feb 27, 2018

In a fork of this repo I have added some more metadata helpful in our stencil templates,

In Schema:

  let isOptional: Bool
  let isMutable: Bool
  let jsonKey: String?
  var hasCustomJsonKey: Bool {
    return jsonKey != nil
  }

Inside JsonParser:

  public var customKeyProperties: [SchemaProperty] {
    return properties.filter { $0.hasCustomJsonKey }
  }

  public var nonCustomKeyProperties: [SchemaProperty] {
    return properties.filter { !$0.hasCustomJsonKey }
  }
  
  public var nonOptionalProperties: [SchemaProperty] {
    return properties.filter { !$0.isOptional }
  }
  
  public var nonOptionalProperties: [SchemaProperty] {
    return properties.filter { $0.isOptional }
  }
  
  public var immutableProperties: [SchemaProperty] {
    return properties.filter { !$0.isMutable }
  }
  
  public var mutableProperties: [SchemaProperty] {
    return properties.filter { $0.isMutable }
  }

I added these arrays allowing for filtering on properties since stencil does not support filtering. Only map.

Here are some use cases for these filtered properties;

CustomStringConvertible

If I declare a protocol in my template.stencil and let that protocol, let's call it MyModel as CustomStringConvertible, we can then give it a default implementation of var description: String that we can override. We don't want to print optional properties without unwrapping them, so we want to first iterate through all nonoptional properties and then unwrap all optional. So we need the nonOptionalProperties and the nonOptionalProperties computed properties, an ugly example of usage:

public extension {{ protocol }} {
    var description: String {
var nonOptional = ""
nonOptional = "{% for p in spec.nonOptionalProperties %}{{p.name}}: `\({{p.name}})`{% if not forloop.last %}, {% endif %}{% endfor %}"
{% if spec.optionalProperties.count > 0 %}
    {% for p in spec.optionalProperties %}
        if let value = {{ p.name }} {
            nonOptional.append(", {{ p.name }}: `\(value)`")
        }
    {% endfor %}
{% endif %}

return nonOptional
    }
}

CodingKeys

Or let's say we want to make MyModel conform to Codable with default implementations, then we want to separate between those properties who have a custom jsonKey and those who have not:

enum {{ codingKeys }}: String, CodingKey {

    //MARK: Custom JSON key cases
{% for customKeyCase in spec.customKeyProperties %}
    case {{ customKeyCase.name }} = "{{ customKeyCase.jsonKey }}"
{% endfor %}

    //MARK: Standard cases
{% if spec.nonCustomKeyProperties.count > 0 %}
    case {% for case in spec.nonCustomKeyProperties %}{{ case.name }}{% if not forloop.last %}, {% endif %}{% endfor %}
{% endif %}
}

Which result in e.g. this Swift code for a Hotel model:

enum HotelCodingKeys: String, CodingKey {

    //MARK: Custom JSON key cases
    case location = "geolocation"

    //MARK: Standard cases
    case name, propertyCode, image, phoneNumber, address
}

For this template:

{
  "title": "Hotel",
  "concreteType": "struct",
  "properties": {
    "name": {"type": "string"},
    "propertyCode": {"type": "string"},
    "image": {"type": "string"},
    "phoneNumber": {"type": "string"},
    "address": {"$ref": "address.json"},
    "location": {"$ref": "location.json", "jsonKey": "geolocation"}
  }
}

I have already implemented this in a fork, do you feel like this is something that you want part of this repo? If so I can create a PR?

@hebertialmeida
Copy link
Owner

Overal I think this is interesting and useful for me too, could you create the PR and I will test it and we continue the improvements.

Couple things:

  1. You propose to remove the required (from JSON Schema) property and add isOptional?
  2. Did you disable SwiftLint? It is important to enforce the code style/convention...

Thank you for working on this!

@hebertialmeida hebertialmeida self-assigned this Feb 27, 2018
@hebertialmeida
Copy link
Owner

Do you still have this fork?

@Sajjon
Copy link
Author

Sajjon commented Mar 11, 2019

@hebertialmeida sorry for slow response, I just created this PR, not mergable, so that you can copy paste/Git cherry pick if you find anything interesting.

#8

@hebertialmeida
Copy link
Owner

Cool, that will be useful

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

No branches or pull requests

2 participants