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

Dynamically create a json structure inside the preprecessor function #328

Closed
break2make opened this issue May 18, 2020 · 11 comments
Closed

Comments

@break2make
Copy link

I have an usecase where I want to find the max of an array. If I have a predefined json struct having a {"key": [12, 13, 14]}, then max() function return the max value 14. However, there are few cases, where I have to generate {"key": [12, 13, 14]} dynamically with variable number of elements in list. Please help to generate a dynamic json structure or update an existing jason structure in plantuml preprocessor.

@abhijeet-pathak
Copy link

Can you please provide an example of your preprocessor function?

@philCryoport
Copy link

philCryoport commented Feb 1, 2024

My use case:

I'm tracking in a sequence diagrams multiple queues which would greatly benefit from the ability to (a) start with an empty JSON array, and then (b) have the ability to add and remove entries.

My queues are:

  • MQTT topic subscribers
  • Messages in a MQTT topic

I'll also comment in the above links

@The-Lum
Copy link
Collaborator

The-Lum commented Apr 21, 2024

Hello @break2make, @philCryoport, @Potherca, and all,

Available from last snapshot (~v1.2024.5beta1), you can now use:

  • %str2json
  • %json_add
  • %json_remove

Then:

  • Could you test to confirm proper operation?
  • or feel free to share your feedback...

From:

See also:

Regards,
Th.

@philCryoport
Copy link

philCryoport commented Apr 22, 2024

Hi @The-Lum -- Trying this out first with a "Hello World":

➜ java --version
openjdk 21.0.2 2024-01-16 LTS
OpenJDK Runtime Environment Temurin-21.0.2+13 (build 21.0.2+13-LTS)
OpenJDK 64-Bit Server VM Temurin-21.0.2+13 (build 21.0.2+13-LTS, mixed mode)
  • I downloaded plantuml-SNAPSHOT.jar from the link you provided above
  • I created a simple file based upon the "Variable Definition" example
  • I ran java -jar plantuml-SNAPSHOT.jar test.puml -- and got a PNG file that matches the diagram in the instructions
  • I then added a remove and an add command to, effectively, change the name attribute:
@startuml
!$a  = 42
!$ab = "foo1"
!$cd = "foo2"
!$ef = $ab + $cd
!$foo = { "name": "John", "age" : 30 }
%json_remove($foo,name)
%json_add($foo,name,"Sally")

Alice -> Bob : $a
Alice -> Bob : $ab
Alice -> Bob : $cd
Alice -> Bob : $ef
Alice -> Bob : Do you know **$foo.name** ?
@enduml

It threw the following error:

java.lang.NullPointerException: value is null
	at net.sourceforge.plantuml.json.JsonObject.add(JsonObject.java:331)
	at net.sourceforge.plantuml.tim.stdlib.JsonAdd.executeReturnFunction(JsonAdd.java:84)
	at net.sourceforge.plantuml.tim.TContext.applyFunctionsAndVariables(TContext.java:486)
	at net.sourceforge.plantuml.tim.TContext.applyFunctionsAndVariablesInternal(TContext.java:431)
	at net.sourceforge.plantuml.tim.TContext.addPlain(TContext.java:391)
	at net.sourceforge.plantuml.tim.TContext.executeOneLineNotSafe(TContext.java:360)
	at net.sourceforge.plantuml.tim.TContext.executeOneLineSafe(TContext.java:321)
	at net.sourceforge.plantuml.tim.TContext.executeLines(TContext.java:295)
	at net.sourceforge.plantuml.tim.TimLoader.load(TimLoader.java:68)
	at net.sourceforge.plantuml.BlockUml.<init>(BlockUml.java:147)
	at net.sourceforge.plantuml.BlockUmlBuilder.init(BlockUmlBuilder.java:144)
	at net.sourceforge.plantuml.BlockUmlBuilder.<init>(BlockUmlBuilder.java:102)
	at net.sourceforge.plantuml.SourceFileReaderAbstract.<init>(SourceFileReaderAbstract.java:98)
	at net.sourceforge.plantuml.SourceFileReader.<init>(SourceFileReader.java:77)
	at net.sourceforge.plantuml.Run.manageFileInternal(Run.java:479)
	at net.sourceforge.plantuml.Run.processArgs(Run.java:404)
	at net.sourceforge.plantuml.Run.manageAllFiles(Run.java:371)
	at net.sourceforge.plantuml.Run.main(Run.java:206)
Error line 8 in file: /foo/test.puml
Some diagram description contains errors

Line 8 is %json_add($foo,name,"Sally")

Note that I tried both "Sally" and Sally (i.e. without the double quotes). In both cases, it threw the same error.

I also tried assigning the return of the remove and the add calls to newly declared variables -- identical NPE to the above...except it doesn't call out line 8, nor does it say "Some diagram description contains errors":

@startuml
!$a  = 42
!$ab = "foo1"
!$cd = "foo2"
!$ef = $ab + $cd
!$foo = { "name": "John", "age" : 30 }
!$foo2 = %json_remove($foo,name)
!$foo3 = %json_add($foo2,name,"Sally")

Alice -> Bob : $a
Alice -> Bob : $ab
Alice -> Bob : $cd
Alice -> Bob : $ef
Alice -> Bob : Do you know **$foo3.name** ?
@enduml

I also tried assigning to the same variable -- identical to the second situation, "value is null" NPE, doesn't call out line 8, nor does it say "Some diagram description contains errors":

@startuml
!$a  = 42
!$ab = "foo1"
!$cd = "foo2"
!$ef = $ab + $cd
!$foo = { "name": "John", "age" : 30 }
!$foo = %json_remove($foo,name)
!$foo = %json_add($foo,name,"Sally")

Alice -> Bob : $a
Alice -> Bob : $ab
Alice -> Bob : $cd
Alice -> Bob : $ef
Alice -> Bob : Do you know **$foo3.name** ?
@enduml

@The-Lum
Copy link
Collaborator

The-Lum commented Apr 23, 2024

Hi @philCryoport,

Thanks a lot for your detailed tests.

Currently the %json_add runs only with JSON Array or Object, as:

@startuml
!$foo = [12, 13]
!$a  = [14, "ab"]
!$foo = %json_add($foo, $a)

Alice -> Bob : $a
Alice -> Bob : $foo
@enduml
@startuml
!$a  = 42
!$foo = { "name": "John", "age" : 30 }
!$foo = %json_remove($foo, name)
!$v = %str2json("[1, 2]")
!$foo = %json_add($foo, "name", $v)

Alice -> Bob : $a
Alice -> Bob : $foo
Alice -> Bob : Do you know **$foo.name** ?
@enduml

And there are some side effects on scalar type (string, integer, boolean, null) [ -> As you point out with your tests].

Then I must to do more boundary check on that.
I must to go to new tests... on scalar...

Thanks for your tests.
See you on next correction,
Regards,
Th.

The-Lum added a commit to The-Lum/plantuml that referenced this issue Apr 24, 2024
That fixes:
- plantuml#328 (comment)

Here is a fix for `int` and `string`, in order to manage:

```puml
%json_add({"age" : 30}, name, 123) '=> {"age":30,"name":123}
```

```puml
%json_add({"age" : 30}, name, Sally) '=> {"age":30,"name":"Sally"}
```

[FYI @philCryoport]
Reagrds,
Th.
@philCryoport
Copy link

Thank you @The-Lum -- lemme know when you have a snapshot build ready and I'll test it on my box:

  • First: the basic "Hello World" as shown above
  • Then: trying it out for my scenario, where I want to
    • (a) adding a specific entry into a JSON string that's tracking unsent messages on a MQTT topic
    • (b) removing a specific entry from that same JSON string -- once we receive a Publish Acknowledgement that a particular message was delivered

@The-Lum
Copy link
Collaborator

The-Lum commented Apr 25, 2024

Hello @philCryoport,

With the last snapshot of yesterday evening you can now test.

Good test...
Don't hesitate to make feedback...

Regards,
Th.

@philCryoport
Copy link

Hi @The-Lum

Yep, tried out the basic stuff with 1.2024.5beta:

@startuml
!$a  = 42
Alice -> Bob : Original $a
!$foo = { "name": "John", "age" : 30 }
Alice -> Bob : Original foo: $foo
!$foo = %json_remove($foo, name)
Alice -> Bob : Revised foo: $foo -- name attribute should be gone
!$v = %str2json("[1, 2]")
!$foo = %json_add($foo, "name", Sally)
Alice -> Bob : Revised foo again: $foo -- name attribute should be "Sally"
!$v = %str2json("[1, 2]")
!$foo = %json_add($foo, "new array", $v)
Alice -> Bob : Revised foo again: $foo -- should have the "new array" of [1,2]
Alice -> Bob : Do you know **$foo.name** ?
@enduml

The basic stuff worked fine:
image

However there's no checking with a json_add to see if the attribute already exists :(

@startuml
!$a  = 42
Alice -> Bob : Original $a
!$foo = { "name": "John", "age" : 30 }
Alice -> Bob : Original foo: $foo
!$foo = %json_add($foo, "name", Sally)
Alice -> Bob : Revised foo again: $foo - should have one name attribute "Sally" - but end up with two "name" attributes
@enduml

Result - two "name" attributes:
image

I also tried removing an attribute that I had already removed:

@startuml
!$a  = 42
Alice -> Bob : Original $a
!$foo = { "name": "John", "age" : 30 }
Alice -> Bob : Original foo: $foo
!$foo = %json_remove($foo, "name")
Alice -> Bob : Revised foo again: $foo - "name" attribute should be gone
!$foo = %json_remove($foo, "name")
Alice -> Bob : Revised foo again: $foo - what happens if I try to remove the "name" attribute when it's already gone?
@enduml

Result - No warning thrown...which might be ok...that depends on the standard being followed:
image

The classic sempf joke is running through my head...

@The-Lum
Copy link
Collaborator

The-Lum commented May 3, 2024

Hi @philCryoport,

Good catch!

Internally plantuml use the minimal-json; then for:

However there's no checking with a json_add to see if the attribute already exists :(

We will now create the new function %json_set a wrapper of set, in order to set the last existing attribute....

And you're right, unit tests look strangely like:

The classic sempf joke is running through my head...

Regards,
Th.

@The-Lum
Copy link
Collaborator

The-Lum commented Sep 8, 2024

Hi all,

[This is an Issue Review] 👀
This is now implemented, we can close this ticket.

Regards.

@The-Lum The-Lum closed this as completed Sep 8, 2024
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

5 participants