I'm looking for a library to convert a text file to JSON.
Do you know which one has the following behavior?
I already test some libraries but without success.
The source files contains a list of key=value pairs, one key per line.
Converting to correct data type is important, my files has:
string keys
number keys
boolean keys
object (JSON) keys
arrays (of simple strings or of JSON objects)
Example
name = "test"
version = 3
enabled = true
fruit = {"type":"orange","color":"orange"}
consumers = ["kids", "adults"]
years = [2014, 2015]
fruits = [{"type":"orange","color":"orange"},{"type":"apples","method":"red"}]
Expected Result after conversion: Valid JSON (don't need style/identation)
{
"name": "test",
"version": 3,
"enabled": true,
"fruit": {
"type": "orange",
"color": "orange"
},
"consumers": [
"kids",
"adults"
],
"years": [
2014,
2015
],
"fruits": [
{
"type": "orange",
"color": "orange"
},
{
"type": "apples",
"method": "red"
}
]
}
The format you're using isn't standardized so I'm doubtful you'll find a package that can parse it out of the box. Your values do look to be valid JSON primitives so you can leverage JSON.parse to parse the right hand side. With that you'd just need a parser to robustly pull out all the raw [key, value] pairs, but most parsers probably try to do more than just that which might not be what you want.
If you know the input will always be clean and don't need a completely robust parser, it's not difficult to roll this yourself:
const data = fs.readFileSync('./data.txt', {encoding: 'utf8'}).split('\n').filter(Boolean)
const obj = {}
for (const line of data) {
const [key, val] = line.split(/\s*=\s*(.+)/)
obj[key] = JSON.parse(val)
}
Related
I am in no way an expert with groovy so please don't hold that against me.
I have JSON that looks like this:
{
"metrics": [
{
"name": "metric_a",
"help": "This tracks your A stuff.",
"type": "GAUGE",
"labels": [
"pool"
],
"unit": "",
"aggregates": [],
"meta": [
{
"category": "CAT A",
"deployment": "environment-a"
}
],
"additional_notes": "Some stuff (potentially)"
},
...
]
...
}
I'm using it as a source for automated documentation of all the metrics. So, I'm iterating through it in various ways to get the information I need. So far so good, I'm most of the way there. The problem is this all needs to be organized per the deployment environment. Meaning, multiple metrics will share the same value for deployment.
My thought was I could create a map with deployment as the key and the metric name for any metric that has a matching deployment as the value. Once I have that map, it should be easy for me to organize things the way they should be. I can't figure out how to do that. The result is all the metric names are added which is expected since I'm not doing anything to filter them out. I was thinking that groupBy would make sense here but I can't figure out how to use it effectively and frankly I'm not sure it will solve my problem by itself. Here is my code so far:
parentChild = [:]
children = []
metrics.each { metric ->
def metricName = metric.name
def depName = metric.meta.findResult{ it.deployment }
children.add(metricName)
parentChild.put(depName, children)
}
What is the best way to create a new map where the values for each key are based off a specific condition?
EDIT: The desired result would be each key in the resulting map would be a unique deployment value from all the metrics (as a string). Each value would be name of each metric that contains that deployment (as an array).
[environment-a:
[metric_a,metric_b,metric_c,...],
environment-b:
[metric_d,metric_e,metric_f,...]
...]
I would use a combo of withDefault() to pre-fill each map-entry value with a fresh TreeSet-instance (sorted no-duplicates set) and standard inject().
I reduced your sample data to the bare minimum and added some new nodes:
import groovy.json.*
String input = '''\
{
"metrics": [
{
"name": "metric_a",
"meta": [
{
"deployment": "environment-a"
}
]
},
{
"name": "metric_b",
"meta": [
{
"deployment": "environment-a"
}
]
},
{
"name": "metric_c",
"meta": [
{
"deployment": "environment-a"
},
{
"deployment": "environment-b"
}
]
},
{
"name": "metric_d",
"meta": [
{
"deployment": "environment-b"
}
]
}
]
}'''
def json = new JsonSlurper().parseText input
def groupedByDeployment = json.metrics.inject( [:].withDefault{ new TreeSet() } ){ res, metric ->
metric.meta.each{ res[ it.deployment ] << metric.name }
res
}
assert groupedByDeployment.toString() == '[environment-a:[metric_a, metric_b, metric_c], environment-b:[metric_c, metric_d]]'
If your metrics.meta array is supposed to have a single value, you can simplify the code by replacing the line:
metric.meta.each{ res[ it.deployment ] << metric.name }
with
res[ metric.meta.first().deployment ] << metric.name
I'm making a script using node.js and i need to parse a script inside a website, exactly i need 2 part not only the entire script. The 2 parts are "stock" and "local" and their values.
<script id="z-vegas-pdp-props" type="application/json">
![CDATA[{
"layout": "cover",
"model": {
"layout": "cover",
"priceInfo": {
"showPriceHint": false,
"priceHintType": ""
},
"mediaInfo": {
"currentIndex": 0
},
"price": {
"currency": "EUR",
"value": 129.99,
"formatted": "129,99 €"
},
"originalPrice": {
"currency": "EUR",
"value": 129.99,
"formatted": "129,99 €"
},
"available": false,
"stock": 0
}
//here the scripts continues but i "trimmed it to make it more easy"
</script>
This is what i made but it's parsing all the code and not only the parts that i need.
let root = HTMLParser.parse(response.body);
let availabiltyDiv = root.querySelector("#z-vegas-pdp-props")
console.log(availabiltyDiv)
The data you're looking for is hiding in json format inside the CDATA in the script. So you first need to extract the json string, parse it and get to the target data. Incidentally, the json string sample in your question is malformed, but is presumably well formed in the actual script. Also, there is no local in your sample, so I'll use another value instead.
All in all:
const jstring = availabiltyDiv.childNodes[0].nodeValue.split('CDATA[')[1].split(']')[0]
const target = JSON.parse(jstring);
#to get to (for example) price and stock:
const price = target.model.price.formatted;
const stock = target.model.stock;
console.log(price,stock)
Output:
"129,99 €" 0
EDIT:
As expalined in the respoinse to your comment, I don't have access to your actual availabilityDiv but you can also try replacing
const jstring = availabiltyDiv.childNodes[0].nodeValue.split('CDATA[')[1].split(']')[0]
with
const jstring = availabiltyDiv.innerHTML.split('CDATA[')[1].split(']')[0]
or with
const jstring = availabiltyDiv.innerText.split('CDATA[')[1].split(']')[0]
and see if they work.
I am building a Azure Logic App which recieves a webhook. I need to parse the body and validate if a array contains any object with a property that matches either of two values, but have no idea how to do it.
Any ideas?
The JSON i am recieving in the webhook is like below, shortened for brevity. I am looking at the components-array:
{
"id": "12601",
"components": [
{
"id": "10021",
"name": "Value1"
},
{
"id": "10022",
"name": "Value2"
},
{
"id": "10023",
"name": "Value3"
}
]
}
From this array I need to output a parameter true/false if any properties with name == "Value1" or "Value" appears.
Is there any syntax similar to LINQ in C#, or do you use a foreach? I have not been able to find any simple way like:
If(Arr.Any(x => x.name == "Value1"))
Perhaps you can use Parse Json to parse the Json string you received, and then use condition to determine whether the name contains value1.
Please refer to my logic app:
I have a map function
function (doc) {
for(var n =0; n<doc.Observations.length; n++){
emit(doc.Scenario, doc.Observations[n].Label);
}
}
the above returns the following:
{"key":"Splunk","value":"Organized"},
{"key":"Splunk","value":"Organized"},
{"key":"Splunk","value":"Organized"},
{"key":"Splunk","value":"Generate"},
{"key":"Splunk","value":"Ingest"}
I"m looking to design a reduce function that will then return the counts of the above values, something akin to:
Organized: 3
Generate: 1
Ingest: 1
My map function has to filter on my Scenario field, hence why I have it as an emitted key in the map function.
I've tried using a number of the built in reduce functions, but I end up getting count of rows, or nothing at all as the functions available don't apply.
I just need to access the counts of each of the elements that appear in the values field. Also, the values present here are representative, there could 100s of different types of values found in the values field for what that's worth.
I really appreciate the help!
Here's sample input:
{
"_id": "dummyId",
"test": "test",
"Team": "Alpha",
"CreatedOnUtc": "2019-06-20T21:39:09.5940830Z",
"CreatedOnLocal": "2019-06-20T17:39:09.5940830-04:00",
"Participants": [
{
"Name": "A",
"Role": "Person"
}
],
"Observations": [
{
"Label": "Report",
},
{
"Label": "Ingest",
},
{
"Label": "Generate",
},
{
"Label": "Ingest",
}
]
}
You can set the map by "value" as your key and associate an increment to that key to make sure a count is maintained. And then you can print your map which should look as you are requesting for.
I have a json data like:
{
"cse_thumbnail": [
{
"width": "188",
"height": "268",
"src": "http://abc.dk"
}
],
"metatags": [
{
"referrer": "origin-when-cross-origin",
"og:image": "http://def.dk"
}
],
"cse_image": [
{
"src": "http://ghi.dk"
}
]
}
There are 3 array lists coming in the JSON. I want to check if the corresponding keys are existing when I'm getting the response:
cse_thumbnail
metatags
cse_image
I'm tried all the key:value pair check in python like (hasattr, key in list etc) which are not working at all.
Please help to get it resolved.
You can use in to check if a key is present
import json
with open('data.json') as thing:
data = json.load(thing)
keys = ('cse_thumbnail', 'metatags', 'cse_image')
for key in keys:
print(key in data)