bkiers / Liqp

An ANTLR based 'Liquid Template' parser and rendering engine.
MIT License
165 stars 94 forks source link

numbers as key name #209

Closed kkms closed 3 years ago

kkms commented 3 years ago

Following example throws me exception, Is it possible to use number as Key?

String testData = "{\n" +
    "  \"Data\": {\n" +
    "    \"1\": {\n" +
    "      \"Value\": \" Data 1\"\n" +
    "    },\n" +
    "    \"2\": {\n" +
    "      \"Value\": \" Data 2\"\n" +
    "    }\n" +
    "  }\n" +
    "}";

Template template = Template.parse("hi {{Data.1.Value}}");
String render = template.render(testData);
System.out.println("Render :"+render);
Exception in thread "main" liqp.exceptions.LiquidException: parser error "extraneous input '1.' expecting {'capture', 'endcapture', 'comment', 'endcomment', RawStart, 'if', 'elsif', 'endif', 'unless', 'endunless', 'else', 'contains', 'case', 'endcase', 'when', 'cycle', 'for', 'endfor', 'in', 'and', 'or', 'tablerow', 'endtablerow', 'assign', 'true', 'false', Nil, 'include', 'with', 'offset', 'continue', 'reversed', 'empty', EndId, Id, RawEnd}" on line 1, index 10
    at liqp.Template$2.syntaxError(Template.java:196)
    at org.antlr.v4.runtime.ProxyErrorListener.syntaxError(ProxyErrorListener.java:41)
    at org.antlr.v4.runtime.Parser.notifyErrorListeners(Parser.java:544)
    at org.antlr.v4.runtime.DefaultErrorStrategy.reportUnwantedToken(DefaultErrorStrategy.java:377)
    at org.antlr.v4.runtime.DefaultErrorStrategy.singleTokenDeletion(DefaultErrorStrategy.java:548)
    at org.antlr.v4.runtime.DefaultErrorStrategy.sync(DefaultErrorStrategy.java:266)
    at liquid.parser.v4.LiquidParser.id2(LiquidParser.java:3970)
    at liquid.parser.v4.LiquidParser.index(LiquidParser.java:4095)
    at liquid.parser.v4.LiquidParser.lookup(LiquidParser.java:3779)
    at liquid.parser.v4.LiquidParser.term(LiquidParser.java:3610)
    at liquid.parser.v4.LiquidParser.expr(LiquidParser.java:3249)
    at liquid.parser.v4.LiquidParser.output(LiquidParser.java:2752)
    at liquid.parser.v4.LiquidParser.atom(LiquidParser.java:370)
    at liquid.parser.v4.LiquidParser.block(LiquidParser.java:241)
    at liquid.parser.v4.LiquidParser.parse(LiquidParser.java:184)
    at liqp.Template.parse(Template.java:207)
    at liqp.Template.<init>(Template.java:83)
    at liqp.Template.parse(Template.java:229)
    at com.resilihealth.seal.hl7.parser.Hl7V2Parser.main(Hl7V2Parser.java:157)
msangel commented 3 years ago

Yes. It is possible. Just configure your own jackson mapper with this feature and use it with the library. In few hours will gave you a sample

msangel commented 3 years ago

If you will be unable to find that method yourself till that time

kkms commented 3 years ago

Thanks @msangel But I think issue is related to Template parsing. number field in the template is causing the issue.

@bkiers

msangel commented 3 years ago

Just dig into this. Yes, this is lexer problem. in place where we have lookup > index > id2 the lexer gives here DoubleNum, as the match string is DoubleNum: 1.. So far have no idea how to fix this properly... as this is lexer problem, not a parser...

bkiers commented 3 years ago

Indeed, a lexer issue. Ruby's Liquid engine handles such cases properly:

data = { 'Data' => { '1' => { 'Value' => 'tobi' }} }
@template = Liquid::Template.parse("hi {{Data.1.Value}}")
puts @template.render(data)
# hi tobi

So it's a bug in Liqp. One I don't really have a nice way of handling though 🤷

bkiers commented 3 years ago

It appear to be valid to put a number as a key only in nested objects. So this is valid:

{ 'Data' => { '1' => { '2' => 'mu' } } }

but this is not:

{ '1' => { 'Data' => { '2' => 'mu' } } }

This means I can recognize a so-called "ID chain" in the lexer (like "Data.1.2") and let the lexer chop this up in a separate method in the 5 tokens: Id, Dot, Id, Dot and Id. I'll give this a try tonight.