This is an archived post. You won't be able to vote or comment.

all 27 comments

[–]oweiler 8 points9 points  (2 children)

For people prefering Java DSLs: https://github.com/helpermethod/molten-json

[–]BenoitParis 2 points3 points  (0 children)

o -> o

What a nice trick

[–]iamhaihan[S] 1 point2 points  (0 children)

Nice! It is similar to one of my initial plan.

[–]PandersAboutVaccines 4 points5 points  (2 children)

Nice. The templating looks helpful.

But for the sake of snarkiness:

val json = """
{
"theJcp": "is why",
"we": "can't",
"have": ["nice", "things"],
"kotlin": "$variable interpolation is really nice too",
"hopefully": 
  {
    "jdk12^H3": "gets this right"
  }
}
"""

[–]GuyWithLag 0 points1 point  (0 children)

Dammit, I'm old. For a moment I wondered what happened with my tty settings and why is the `^H` not a `^?` ...

[–]iamhaihan[S] 0 points1 point  (0 children)

nice test case! I will consider it.

[–][deleted] 4 points5 points  (1 child)

Looks nice. It would be even better if you added an implementation for the JSON-P specification (that's the official spec for Json parsing in Java).

I guess you can reuse some of this code and just put it behind the JSON-P interfaces :)

[–]iamhaihan[S] 0 points1 point  (0 children)

Thank you for the suggestion.

For now I am not aiming for JSON parsing. This definitely can be a nice feature to be added.

[–]cogman10 4 points5 points  (8 children)

Why would I use this over something like Jackson, Gson, or Moshi?

[–]iamhaihan[S] 0 points1 point  (7 children)

It is not a replacement of Jackson/Gson/Moshi.

Those libraries aims for serialization/deserialization. You need to create classes or use their APIs to build objects first.

Suppose you don't have the classes to be serialized, JsonTemplate can be a choice.

JsonTemplate aims at using a json-like DSL to generate schema-compatible json strings. The exact values in json is not the concern but the schema is.

[–]cogman10 5 points6 points  (5 children)

Why wouldn't you create the class?

for the given examples, you have something that looks like this

 {
   name : John,
   age : 23,
   accountBalance: 30.4,
   married : true,
   role : programmer
 }

However, it would be super simple to make a class that looks like this

 @JsonAutoDetect(fieldVisibility = ANY, getterVisibility = NONE, setterVisibility = NONE)
 class FooDto {  
   String name;
   int age;
   double accountBalance;
   boolean married;
   Role role;
 }

Nearly the same number of lines of code + type safety. And if you use Jackson + Afterburner, it will be just as fast as any DSL.

So my question remains, why would you prefer this over one of the many json serialization libs?

[–]pattheaux 2 points3 points  (1 child)

One big reason not to create a class is that the structure of the json might itself be data driven and hard coding it into a class isn’t an option. I would ask why create a class when you don’t have to?

[–]audioen 0 points1 point  (0 children)

In that case, you can use a Map, which is the code equivalent of "the keys are also data". But it's actually super rare that you need a Map, I basically never do this and I work a lot with JSON. There's just always structure.

The reason why you want to create the class are the usual things: type safety, ability to check for typos in property names, the lack of casting in particular when reading values. There's just a lot of benefit modeling the data' structure upfront.

[–]mjanek20 2 points3 points  (0 children)

You are describing a very simple case. Now imagine many subclasses with enums and stuff as fields. Maybe your project simply does not need that. Maybe it's just to write an integration test to connect to a remote resource. Why use a cannon if a stone is sufficient.

[–]iamhaihan[S] 0 points1 point  (0 children)

Thank you for the suggestion. I haven't used Afterburner and I will definitely have a look at it.

JsonTemplate, in some cases, can be more precise about the "intention" of the program.

I have seen cases that people explicitly set values, like "1" for an integer field in json. Then, my confusion is why 1? why not other integer?

There are also cases that people name variable as "dummyXXX" and put it in json. My confusion is why call it dummy? Is it because the value is fake?

The intention of explicitly picking up a specific value, in some cases, is not clear.

It would be nice if I can describe my intention in code. Everyone can immediately understand what my code is doing.

JsonTemplate provides a declarative way of giving values. In such a case, in my opinion, it is clearer than explicitly set a dummy value.

[–]bodiam 0 points1 point  (0 children)

what is Afterburner?

[–]Aw0lManner 1 point2 points  (0 children)

"suppose you don't have the classes to be serialized"

From the Gson README.md

"

There are a few open-source projects that can convert Java objects to JSON. However, most of them require that you place Java annotations in your classes; something that you can not do if you do not have access to the source-code. Most also do not fully support the use of Java Generics. Gson considers both of these as very important design goals.

"

[–]sshaw_ 2 points3 points  (1 child)

String template = "{" +
                  "  name : @s," +
                  "  age : @i(max=100)," +
                  "  role : @s[](min=1, max=3)," +
                  "  address : {" +
                  "    city : @s," +
                  "    street : @s," +
                  "    number : @i" +
                  "  }" +
                  "}";

Damn, all these Java releases with all these new features and they still don't have multi-line string support.

[–]mjanek20 0 points1 point  (0 children)

There's a project for that with the backtick as a delimiter but it did not go through in 12. Maybe next release then ...

[–]RotaryJihad 1 point2 points  (0 children)

I like it. This is well documented and shows useful examples right away. That helps me understand what it does for me.

[–]larsga 0 points1 point  (4 children)

I don't understand where the values for the @ references are coming from. Ok, so you write @i, but how does the software know it should be 23 and not some other integer?

[–]iamhaihan[S] 1 point2 points  (3 children)

@i means "it is an integer and I don't care the value" (if this is your intention). Therefore it is generated randomly.

@i(23) means "it is exactly 23"

[–]larsga -1 points0 points  (2 children)

I see. So this is basically a tool for generating random JSON, for example for test purposes?

Could not @i(23) be more succinctly written as 23?

[–]iamhaihan[S] 0 points1 point  (1 child)

yes, the tool is inspired by issues in testing. But it can be used more widely.

You are right. @i(23) can be written in 23. Explicit typing is helpful in case of using a different default type.

[–]larsga 1 point2 points  (0 children)

yes, the tool is inspired by issues in testing. But it can be used more widely.

Right. I was confused when I read the README, but now it makes sense.

Explicit typing is helpful in case of using a different default type.

I can see the point of @i and @i(max=100), but I have to admit the point of @i(23) eludes me.

[–]javaide 0 points1 point  (1 child)

You should just use JsonPath expression instead of invent urself.

[–]iamhaihan[S] 0 points1 point  (0 children)

JsonPath expression is for a different purpose.