JSON Best Practice for Property Names - json

Is it "best practice" to use a GUID as a property name? (see sample JSON below)
{
"ErrorType": 0,
"I9e4f0477549111d997e0acd5cbb90d3f": {
"statusCode": "0",
"guid": "I9e4f0477549111d997e0acd5cbb90d3f",
"moreProperties": "more values"
},
"N51D209F0505711DEA52DFAD621371B7C": {
"statusCode": "0",
"guid": "N51D209F0505711DEA52DFAD621371B7C",
"moreProperties": "more values"
}
}
I would assume no because now isn't the whole "object" part of JSON gone? You no longer have access to the namespace because the property name is random. And serializing (using JSON.NET) is no longer a one-liner.
Furthermore there is repeated data. The GUID is the name of the property and within that property is another object with a property name of "guid". Data normalization is not being considered.
I'm not writing this JSON just consuming it. If I was writing this JSON I would rewrite it to this:
{
"ErrorType": 0,
"guids": [
{
"statusCode": "0",
"guid": "I9e4f0477549111d997e0acd5cbb90d3f",
"moreProperties": "more values"
},
{
"statusCode": "0",
"guid": "N51D209F0505711DEA52DFAD621371B7C",
"moreProperties": "more values"
}
]
}
Thoughts?

If you're searching for objects by GUID in Javascript, it's certainly better to use the GUID as a key, allowing you to write obj[someGuid].
Otherwise, it depends on the environment and usage; please provide more details.

As SLaks points out, it depends on how you are trying to use the JSON. Given:
allObjects = {
"ErrorType": 0,
"I9e4f0477549111d997e0acd5cbb90d3f": {
"statusCode": "0",
"guid": "I9e4f0477549111d997e0acd5cbb90d3f",
"moreProperties": "more values"
},
"N51D209F0505711DEA52DFAD621371B7C": {
"statusCode": "0",
"guid": "N51D209F0505711DEA52DFAD621371B7C",
"moreProperties": "more values"
}
}
myguid = "N51D209F0505711DEA52DFAD621371B7C";
you can simply access the data like allObjects[myguid]["moreProperties"]. If you generated the JSON as you suggest (without the guid as a key) and had to pull a value pertaining to a particular guid you would be forced to iterate over the array items and check for guid, like
for (var subObj in allObjects) {
if (subObj['guid'] = myguid) {
// you found it, store it and...
break;
}
}

Related

Best Practice Design typed JSON Objects

Currently we are designing a System that will send JSON Objects to registered consumers. The consumers will be able to register for different Object Types that they want to receive. Currently we are designing the JSON Objects that will be consumed by the registered consumers.
As we see there are two possible approaches to define typed JSON Objects.
A generic JSON Object that has some properties set or it has them not set:
{
"timestamp": 1589448935,
"customer_id": "123123123123",
"message": {
"title": "Desired Title",
"text": "The Text of the Message",
}
}
{
"timestamp": 1589448935,
"customer_id": "123123123123",
"message": {
"title": "Desired Title",
"text": "The Text of the Message",
"avatar": "http://avatar.io/avatar"
}
}
A Type field on each JSON Object that specifies which Type this object is from:
{
"timestamp": 1589448935,
"customer_id": "123123123123",
"type": "simple_message",
"message": {
"title": "Title",
"text": "Message",
}
}
{
"timestamp": 1589448935,
"customer_id": "123123123123",
"type": "avatar_message",
"message": {
"title": "Title",
"text": "Message",
"avatar": "http://www.avatar.io/avatar"
}
}
From our point of view a more generic approach would be easier to handle within our system, because we would not need to handle multiple types, we just can append a property or leave it away.
From point of view of a developer I could imagine that a type field could help the developer when handling such objects (f.e. mapping them to objects) or switch on the type field to execute some specific logic.
Finally, to my question - which style is the one to be preferred (best-practice) when we want to make the life for consumers as easy as possible and why? Is there a best-practice approach for typed json objects?
If you are set on a generic application/json response then I would go with your option #2.
That "type" doesn't hurt and can only help clarify what that response is.

How to remove one property from json input message using replace() expression in azure logic app?

{
"metadata": {
"id": "2",
"uri": "3",
"type": "2"
},
"Number": "2323600002913",
"Date": "04/21/2009",
"postingDate": "00/00/0000",
"ata": {
"results": [
{
"metadata": {
"id": "r",
"uri": "e2",
"type": "s2"
},
"item": "000010",
"data":"ad"
}
]
}
}
want to remove metadata property from above json message and output should be like below
{
"Number": "2323600002913",
"Date": "04/21/2009",
"postingDate": "00/00/0000",
"ata": {
"results": [
{
"item": "000010",
"data":"ad"
}
]
}
}
I tried with removeProperty() which is working for root level metadata but inside metadata not removed.
how to use replace() in this case or anything else to only remove metadata.
The simplest way is use inline code, cause even with removeProperty() expression to remove the metadata under results, it will return the results array data not the whole json data. Then you will have to combine them, it's not a convenient way.
And with inline code you could refer to my below picture. The variable json is the value from triggerbody, then just delete the node or key and return the json variable. And with this way, even you want to delete many metadata in the array, you could add a for loop to delete it, just think of it as plain js code.
Update:if you want to get value from variable,cause no support expression to get value from variable so use the below expression.
var json =wworkflowContext.actions.Initialize_variable.inputs.variables[0].value;
And about how to loop the array in the json refer to my below pic.

rename invalid keys from JSON

I have following flow in NIFI , JSON has (1000+) objects in it.
invokeHTTP->SPLIT JSON->putMongo
Flow works fine, till I receive some keys in json with "." in the name. e.g. "spark.databricks.acl.dfAclsEnabled".
my current solution is not optimal, I have jotted down bad keys, and using multiple replace text processor to replace "." with "_". I am not using REGEX, I am using string literal find/replace. So each time I am getting failure in putMongo processor, I am inserting new replaceText processor.
This is not maintainable. I am wondering if I can use JOLT for this? couple of info regarding input JSON.
1) no set structure, only thing that is confirmed is. everything will be in events array. But event object itself is free form.
2) maximum list size = 1000.
3) 3rd party JSON, so I cant ask for change in format.
Also, key with ".", can appear anywhere. So I am looking for JOLT spec that can cleanse at all level and then rename it.
{
"events": [
{
"cluster_id": "0717-035521-puny598",
"timestamp": 1531896847915,
"type": "EDITED",
"details": {
"previous_attributes": {
"cluster_name": "Kylo",
"spark_version": "4.1.x-scala2.11",
"spark_conf": {
"spark.databricks.acl.dfAclsEnabled": "true",
"spark.databricks.repl.allowedLanguages": "python,sql"
},
"node_type_id": "Standard_DS3_v2",
"driver_node_type_id": "Standard_DS3_v2",
"autotermination_minutes": 10,
"enable_elastic_disk": true,
"cluster_source": "UI"
},
"attributes": {
"cluster_name": "Kylo",
"spark_version": "4.1.x-scala2.11",
"node_type_id": "Standard_DS3_v2",
"driver_node_type_id": "Standard_DS3_v2",
"autotermination_minutes": 10,
"enable_elastic_disk": true,
"cluster_source": "UI"
},
"previous_cluster_size": {
"autoscale": {
"min_workers": 1,
"max_workers": 8
}
},
"cluster_size": {
"autoscale": {
"min_workers": 1,
"max_workers": 8
}
},
"user": ""
}
},
{
"cluster_id": "0717-035521-puny598",
"timestamp": 1535540053785,
"type": "TERMINATING",
"details": {
"reason": {
"code": "INACTIVITY",
"parameters": {
"inactivity_duration_min": "15"
}
}
}
},
{
"cluster_id": "0717-035521-puny598",
"timestamp": 1535537117300,
"type": "EXPANDED_DISK",
"details": {
"previous_disk_size": 29454626816,
"disk_size": 136828809216,
"free_space": 17151311872,
"instance_id": "6cea5c332af94d7f85aff23e5d8cea37"
}
}
]
}
I created a template using ReplaceText and RouteOnContent to perform this task. The loop is required because the regex only replaces the first . in the JSON key on each pass. You might be able to refine this to perform all substitutions in a single pass, but after fuzzing the regex with the look-ahead and look-behind groups for a few minutes, re-routing was faster. I verified this works with the JSON you provided, and also JSON with the keys and values on different lines (: on either):
...
"spark_conf": {
"spark.databricks.acl.dfAclsEnabled":
"true",
"spark.databricks.repl.allowedLanguages"
: "python,sql"
},
...
You could also use an ExecuteScript processor with Groovy to ingest the JSON, quickly filter all JSON keys that contain ., perform a collect operation to do the replacement, and re-insert the keys in the JSON data if you want a single processor to do this in a single pass.

How do i document optional RESTful JSON API attributes?

I've been trying to figure out how to design the documentation for an API I'm building. I've been using Swagger (swagger.io) along with JSONSchema to help me structure the documentation, but I've run into a snag. Some of our object will have lots of what we call "metadata" attached to them, which is basically an arbitrary and variable dictionary of key/values. For example:
{
"id": "aabbbccdd",
"name": "Object 1",
"metadata": {
"attributeA": "This is a text attribute",
"attributeB": {
"key1": "complex attribute",
"key2": "complex attribute 2",
},
"attributeC": 1234
}
},
{
"id": "eeffffggghh",
"name": "Object 2",
"metadata": {
"attributeA": "This is a text attribute with a different value",
"attributeD": "Another text attribute",
"attributeE": True
}
}
So I could document the object representation by enumerating all the metadata attributes, but the list is long and will likely vary over time.
Is there another way to approach documenting this, or designing the API in a different way?

How to do deep sets and gets in Go's map[string]interface{}?

If I have some arbitrary JSON how can I do deep sets and gets on the nested properties using a slice of map keys and/or slice indexes?
For example, in the following excerpt from the JSON API example:
{
"data": [{
"type": "posts",
"id": "1",
"title": "JSON API paints my bikeshed!",
"links": {
"self": "http://example.com/posts/1",
"author": {
"self": "http://example.com/posts/1/links/author",
"related": "http://example.com/posts/1/author",
"linkage": { "type": "people", "id": "9" }
}
}
}]
}
I'd like to get the string "9" located at data.0.links.author.linkage.id using something like:
[]interface{}{"data",0,"links","author","linkage","id"}
I know the ideal way to do this is to create nested structs that map to the JSON object which I do for production code, but sometimes I need to do some quick testing which would be nice to do in Go as well.
You have stretchr/objx that provide a similar approach.
Example use:
document, _ := objx.FromJSON(json)
document.Get("path.to.field[0].you.want").Str()
However, unless you really don't know at all the structure of your JSON input ahead of time, this isn't the preferred way to go in golang…