JKISoftware / JKI-JSON-Serialization

JSON Serialization & Deserialization Library for LabVIEW
http://jki.net/tools#json
BSD 3-Clause "New" or "Revised" License
25 stars 10 forks source link

Deserialising JSON with variable property names #26

Closed TAGC closed 7 years ago

TAGC commented 7 years ago

I'm trying to deserialise a JSON document containing variable field names, and I'm unsure how to do this using JKI JSON.

For example, consider the following document:

{
    "abs_bar": {
        "messageId": 500,
        "canPort": 1,
        "repeatRate": 50
    },
    "foo": {
        "messageId": 10,
        "canPort": 0,
        "repeatRate": 50
    }
}

I don't know the fields of the document in advance - I'd like to deserialise this to a dictionary where the key is the "message definition name" and the value is a "message definition" cluster, and go from there. I've been able to do this pretty easily in Python and C#, but unfortunately LabVIEW is not a very nice language and most things take a lot more effort in it.

LabVIEW does not have the native concept of a "map", so I attempted to deserialise this as an array of clusters, where each cluster contains a string (for the name) and a "message definition" cluster.

json deserialisation snippet

I didn't really expect this to work and it doesn't seem to. This is what I see on the front panel after running this:

image

What's the proper way to go about this?

JKSH commented 7 years ago

@TAGC Launch the VI Package Manager and install the OpenG toolkit. Pass your unflattened variant into Get Cluster Element Names.vi -- this will give you an array of names of your 2 top-level objects: ["abs_bar", "pressure_reading"]. Then, pass the variant and one field name into Get Cluster Element by Name.vi to extract your child object.

FYI, a LabVIEW cluster is analogous to a JSON object. In your code, you put a string + cluster inside an array inside a cluster inside a cluster, which conceptually converts to this document:

{
    "": {
        "": [
            {
                "": "",
                "txDefinition": {
                    "repeatRate": 0,
                    "canPort": 0,
                    "messageId": 0
                }
            }
        ]
    }
}
TAGC commented 7 years ago

@JKSH Thanks, that's helped me out!

Here's what I've got:

json deserialisation snippet 2

And here's the result, working as intended:

labview_2017-08-29_11-19-20

TAGC commented 7 years ago

Actually, it's not quite there yet. I should be using the JSON deserialisation library again on the second step - otherwise it mixes up the fields.

TAGC commented 7 years ago

Got it:

json deserialisation snippet 3

Just needed to chuck an Adapt To Type.vi in the middle.

This properly handles the case where the properties in the JSON document are in mixed-up order (as it should, since JSON object key/value pairs are meant to be treated as unordered).

labview_2017-08-29_11-41-57

francois-normandin commented 7 years ago

This one will work with your initial JSON string. Note that it uses "Cluster to Array of VData" from the OpenG palette instead, so you don't need to add the definition name in an extra level.

image

image

PrateekGoyal18 commented 4 years ago

Hey @TAGC and @francois-normandin , my json data is something like this { "Currents" : { "I1" : 2.412445, "I2" : 2.607605, "I3" : 2.655672 }, "Date" : "15-11-2019", "Frequency" : 49.99259, "Power Factors" : { "Q1" : 0.997155, "Q2" : 1, "Q3" : 0.988455 }, "Powers" : { "KA1" : 466.713, "KA2" : 517.551, "KA3" : 533.6165, "KT1" : 465.3853, "KT2" : 517.551, "KT3" : 527.4558, "KV1" : 35.17823, "KV2" : 0, "KV3" : 80.85116 }, "THDs" : { "THDC1" : 64.92453, "THDC2" : 59.34635, "THDC3" : 54.73608, "THDV1" : 1.798943, "THDV2" : 2.569078, "THDV3" : 1.955434 }, "Time" : "10-27-11am", "Voltages" : { "V1" : 231.1034, "V12" : 400.4179, "V2" : 231.2728, "V23" : 400.3139, "V3" : 230.767, "V31" : 400.1738 } }

And I need to retrieve the value of each individual field like I2, V23 etc and store them in a variable or an array. Can you help me out to do this ?

TAGC commented 4 years ago

@PrateekGoyal18 Afraid not sorry, I don't work with LabVIEW anymore.

francois-normandin commented 4 years ago

@PrateekGoyal18 You simply have to build a cluster of the information matching your JSON string. In this example, I just added Currents>>I1

image

And then added some "Powers" cluster as well. You can create a typedef that matches your expected JSON string content and retrieve only those you need.

image

PrateekGoyal18 commented 4 years ago

@francois-normandin really thanks for the solution. It worked like a charm and I can't be more thankful to you.