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

Pyish String representations of objects #581

Merged
merged 10 commits into from
Jan 19, 2021
Merged

Conversation

jasmith-hs
Copy link
Contributor

In Jinjava when a Map object is resolved as a string, the output differs from what the output would be using Jinja. Also, the output of collections differs from how Jinja handles them.

Input Jinja Output Current Jinjava Output
{{ {'foo': 'a', 'bar': 'b'} }} {'foo': 'a', 'bar': 'b'} {foo=a, bar=b}
{{ ['a', 'b'] }} ['a', 'b'] [a, b]

The current way that Jinjava maps objects to string values is not done like in python.

This PR adds a flexible solution to this problem by adding a config option to use a new PyishObjectMapper class to map objects to string values. When using this mapper, by default, all object classes will have their toString() method used to serialize them to python strings. However, by default, a Map, and Collection object will be serialized using Jackson's default JSON serialization as a container. This results in the string output matching up with the desired pythonic string representation. Other classes can be added to this as well if their toString() method does not produce a python string OR they can implement the PyishSerializable interface.

When a class implements the PyishSerializable interface, it will get a default method toPyishString() that calls toString() providing 2 options:

  • toString() can be overridden (from Object or whatever) to return a python string representation
  • toPyishString() can be overridden to return a python string representation if the toString() method needs to remain untouched/different for other purposes.

Here's a minimal example where when the class is converted to a string in Jinjava, it's shown as a dictionary with first_name, last_name included and without the email address:

public class User implements PyishSerializable {
  private String firstName;
  private String lastName
  private String email;
  ...
  @Override
  public String toPyishString() {
    return String.format(
      "{'first_name': '%s', 'last_name': '%s'}",
      firstName,
      lastName
    );
  }
}

Some additional HubSpot specific usefulness, a row from the {{ hubdb_table_rows(123456) }} function returns a result like:
[{id=12345, createdAt=1542736419000, path='some_path', name='some name', 1='{type=string, value=column value}'}]. This is unintuitive because those aren't the names of the attribute as they are accessed in HubL. Using PyishSerializable would allow for the Jinjava string representation of this result to be like a python dictionary.

@boulter @mattcoley I am curious what your thoughts are on this.

@boulter
Copy link
Contributor

boulter commented Jan 15, 2021

Interesting. Seems like a good approach.

@@ -221,6 +227,7 @@ public ExecutionMode getExecutionMode() {
private int maxMacroRecursionDepth;
private boolean failOnUnknownTokens;
private boolean nestedInterpretationEnabled = true;
private boolean usePyishObjectMapper = false;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is disabled by default, as it intentionally makes changes to the output. This may be changed to be enabled by default after a major release

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

Successfully merging this pull request may close these issues.

2 participants