Skip to content

Pyish String representations of objects#581

Merged
jasmith-hs merged 10 commits into
masterfrom
jinjava-serializable
Jan 19, 2021
Merged

Pyish String representations of objects#581
jasmith-hs merged 10 commits into
masterfrom
jinjava-serializable

Conversation

@jasmith-hs

Copy link
Copy Markdown
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

boulter commented Jan 15, 2021

Copy link
Copy Markdown
Contributor

Interesting. Seems like a good approach.

private int maxMacroRecursionDepth;
private boolean failOnUnknownTokens;
private boolean nestedInterpretationEnabled = true;
private boolean usePyishObjectMapper = false;

Copy link
Copy Markdown
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