mongodb import object with numbers as keys results in array - json

I have a simple .json which I am trying to import:
{
"data": {
"plans": {
"1": "14",
"2": "20",
"3": "40"
}
}
}
When I use MongoDB Compass to directly import the json file, the plans object is converted into an array:
{ "_id": { "$oid": "5fe3ff5d909016064978f2bd" }, "plans": [null, "14", "20", "40"] }
Am I doing something wrong? Or can I not use numbers as keys in JSON

MongoDB uses BSON, the following note is from that spec:
Array - The document for an array is a normal BSON document with integer values for the keys, starting with 0 and continuing sequentially. For example, the array ['red', 'blue'] would be encoded as the document {'0': 'red', '1': 'blue'}. The keys must be in ascending numerical order.
The object format you are using matches that description, so some drivers will confuse it for an array.
It might be that the data is being stored properly, but when you query it, the client is converting to an array.
Try retrieving the document with something else, perhaps the mongo shell.

Related

Object or Array in json

I am trying to get json but am not sure how to read it. Here is the ouput of the json. Is quoteResponse an array or an object? also result is an array or an object? Thanks.
{
"quoteResponse": {
"result": [{
"language": "en-US",
"region": "US",
"quoteType": "EQUITY",
"quoteSourceName": "Delayed Quote",
"sourceInterval": 15,
"exchangeTimezoneName": "America/New_York",
"exchangeTimezoneShortName": "EDT",
"pageViews": {
"shortTermTrend": "UP",
"midTermTrend": "UP",
"longTermTrend": "UP"
},
"gmtOffSetMilliseconds": -14400000,
"marketState": "CLOSED",
"market": "us_market",
"priceHint": 2,
"esgPopulated": false,
"tradeable": true,
"triggerable": true,
"exchange": "NYQ",
"regularMarketPrice": 47.23,
"postMarketChangePercent": 0.0,
"postMarketTime": 1568407854,
"postMarketPrice": 47.23,
"postMarketChange": 0.0,
"regularMarketChangePercent": 0.66070205,
"exchangeDataDelayedBy": 0,
"regularMarketTime": 1568404920,
"regularMarketChange": 0.31000137,
"regularMarketVolume": 295978,
"regularMarketPreviousClose": 46.92,
"fullExchangeName": "NYSE",
"longName": "Cabot Corporation",
"shortName": "Cabot Corporation",
"symbol": "CBT"
}],
"error": null
}
}
Your quoteResponse is an object as
JSON objects are surrounded by curly braces {}.
They are written in key/value pairs.
Extract from your original JSON to have it directly in my answer for the purpose of comparison.
{
"quoteResponse": {
"result": [{
"language": "en-US"
"pageViews": {
"shortTermTrend": "UP"
}]
}
}
The result is just an array.
A bit offtopic, but maybe interesting:
I landed on a page which describe Javascript object literals and those are pretty similar to JSON but not the same. JSON derives from Javascript object literal syntax, so the syntax of both are very similar, one directly noticeable difference is that all names in JSON must be wrapped in double quotes.
JavaScript objects can also contain code (functions) and references to other objects. Their keys can be strings, numbers and symbols. etc.
This is an object which is shown by {}.
An array is contained in square brackets [].
You can also have an array of objects [{},{}] - just like the result in your example. You can keep on nesting.
quoteResponse is an object, its value is contained within braces {...}.
result is an array, it is contained within brackets [...].
quoteResponse is an object. It has properties result and error. In json object has following format {property: value, property2: value}
result is an array in json arrays has following format array: [{}, {}...]
quoteResponse is a JSONObject and result is a JSONArray. A JSONObject can be identified by the enclosing curly braces
{"quoteResponse":{"result":[{"language":"en-US","region":"US","symbol":"CBT"}],"error":null}}
Whereas a JSONArray can be identified by the enclosing box brackets as in result.
"result":[{"language":"en-US","region":"US","regularMarketChange":0.31000137,"regularMarketVolume":295978,"regularMarketPreviousClose":46.92,"fullExchangeName":"NYSE","longName":"Cabot Corporation","shortName":"Cabot Corporation","symbol":"CBT"}]

How to take key value pairs and turn them into an array of objects using JMESPath

I'm looking to change the data structure of a 3rd party API using JMESPath and haven't been able to figure out how to take a single object of key-value pairs and restructure this to an array of objects, each containing key-value pairs.
I've gone through all of the JMESPath docs and examples without finding the specific data structure I've been working with. I've tried using the keys(#) and values(#) built-in functions to grab the key and values of these pairs, but haven't been able to join them together into a single array.
Here is my original JSON data
{
"time": 32,
"terms": {
"192.168.10.121": 84,
"154.223.10.121": 12,
"112.149.10.121": 6
}
}
I'm trying to convert the above JSON data to the following strucutre using JMESPath.
{
"data": [
{ "ip_address": "192.168.10.121", "count": 84 },
{ "ip_address": "154.223.10.121", "count": 12 },
{ "ip_address": "112.149.10.121", "count": 6 }
]}
I've been able to create an array of the keys or an array of values, but not able to create the array of objects containing key-value pairs.
terms.{ data: keys(#)}
terms.{ data: values(#)}
Result when using terms.{ data: keys(#)}
{
"data": [
"192.168.10.121",
"154.223.10.121",
"112.149.10.121"
]}
Result when using terms.{ data: values(#)}
{
"data": [
84,
12,
6
]}
Those two functions seem like the only functions I can use to pull the keys and values from an object containing key-value pairs not originally within an array. From what I can tell, I'm not able to combine both of those functions to output a single array like my example above.
I'm not even sure this is possible using JMESPath. Any expert opinion would be greatly appreciated.
Context
jmespath query language
how to re-normalize data from one structure (schema) to another
how to effectively iterate and filter on object properties (name-value pairs)
Pitfalls
Generally speaking, jmespath is highly flexible in iterating sequentially-indexed arrays, but much less flexible in iterating over object properties
Most transformations with jmespath become extremely cumbersome when the goal is to iterate over object properties
Usually you can produce any arbitrary output in jmespath if you are willing to "manually construct" the output by hand ... this is usually the trade-off when dealing with iterating over object properties (aka name-value pairs)
Example
Given the following original dataset ...
{"time": 32,
"terms": {
"192.168.10.121": 84,
"154.223.10.121": 12,
"112.149.10.121": 6
}
}
... the following jmespath query ...
{"data": [
{ "ip_address": #.terms|keys(#)[0], "count": #.terms|values(#)[0] }
,{ "ip_address": #.terms|keys(#)[1], "count": #.terms|values(#)[1] }
,{ "ip_address": #.terms|keys(#)[2], "count": #.terms|values(#)[2] }
]}
... produces the following result
{"data": [
{ "ip_address": "192.168.10.121", "count": 84 },
{ "ip_address": "154.223.10.121", "count": 12 },
{ "ip_address": "112.149.10.121", "count": 6 }
]}

Parsing and manipulating json in Scala

I have this JSON that is returned from a REST-service I'm using.
{
"id": "6804",
"signatories": [
{
"id": "12125",
"fields": [
{
"type": "standard",
"name": "fstname",
"value": "John"
},
{
"type": "standard",
"name": "sndname",
"value": "Doe"
},
{
"type": "standard",
"name": "email",
"value": "john.doe#somwhere.com"
},
{
"type": "standard",
"name": "sigco",
"value": "Company"
}
]
}
]
}
Currently I'm looking into a way to parse this with json4s, iterating over the "fields" array, to be able to change the property "value" of the different objects in there. So far I've tried a few json libs and ended up with json4s.
Json4s allows me to parse the json into a JObject, which I can try extract the "fields" array
from.
import org.json4s._
import org.json4s.native.JsonMethods._
// parse to JObject
val data = parse(json)
// extract the fields into a map
val fields = data \ "signatories" \ "fields"
// parse back to JSON
println(compact(render(fields)))
I've managed to extract a Map like this, and rendered it back to JSON again. What I can't figure out though is, how to loop through these fields and change the property "value" in them?
I've read the json4s documentation but I'm very new to both Scala and it's syntax so I'm having a difficult time.
The question becomes, how do I iterate over a parsed JSON result, to change the property "value"?
Here's the flow I want to achieve.
Parse JSON into iterable object
Loop through and look for certain "names" and change their value, for example fstname, from John to some other name.
Parse it back to JSON, so I can send the new JSON with the updated values back.
I don't know if this is the best way to do this at all, I'd really appreciate input, maybe there's an easier way to do this.
Thanks in advance,
Best regards,
Stefan Konno
You can convert the json into an array of case class which is the easiest thing to do. For example: you can have case class for Fields like
case class Field(`type`: String, name: String, value: String)
and you can convert your json into array of fields like read[Array[Field]](json) where json is
[
{
"type": "standard",
"name": "fstname",
"value": "John"
},
...
]
which will give you an array of fields. Similarly, you can model for your entire Json.
As now you have an array of case classes, its pretty simple to iterate the objects and change the value using case classes copy method.
After that, to convert the array of objects into Json, you can simply use write(objects) (read and write functions of Json4s are available in org.json4s.native.Serialization package.
Update
To do it without converting it into case class, you can use transformField function
parse(json).transformField{case JField(x, v) if x == "value" && v == JString("Company")=> JField("value1",JString("Company1"))}

Querying nested arrays of hashes in Postgres JSON datatype?

So I've read through the Postgres JSON querying examples and I'm pretty sure there's no way to query our data as structured, but I wanted to make absolutely sure as it will require multiple changes to our code base :)
We are currently storing the following data in a serialized text field in Postgres. We would like to be able to query against the values, which are either nil or arrays-of-hashes [{a : 1, b: 2},{c: 3, d: 4}] to see if the hash values themselves contain a hash witch has a certain value (in the example below facebook or 102).
{ "statuses": nil,
"services_and_accounts": [
{
"id": "facebook",
"enabled": false
},
{
"id": 102,
"enabled": false
}
]
}
Is this possible in pure SQL using the JSON datatype?

Access object returned from Newtonsoft json DeserializeObject

Should be a no brainer, but I'm can't seem to access the elements returned from Newtonsoft's json deserializer.
Example json:
{
"ns0:Test": {
"xmlns:ns0": "http:/someurl",
"RecordCount": "6",
"Record": [{
"aaa": "1",
"bbb": "2",
},
{
"aaa": "1",
"bbb": "2",
}]
}
}
var result = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(somestring);
Stripping out the json up to the Record text, i can access the data without issue.
i.e. result.Recordcount
If i leave the json as shown above, can someone enlighten me how to access Recordcount?
All inputs appreciated. Thanks!
For those JSON properties that have punctuation characters or spaces (such that they cannot be made into valid C# property names), you can use square bracket syntax to access them.
Try this:
int count = result["ns0:Test"].RecordCount;