[
{
"ID": 5,
"Name": "pratik"
},
{
"ID": 6,
"Name": "pratiksha"
},
{
"ID": 7,
"Name": "pratikshaman"
}
]
I want to display only : 6 Pratiksha
Not too clear on what your trying to achieve... is this what your wanting?
//The json string
var jsonString = '[{"ID":5,"Name":"pratik"},{"ID":6,"Name":"pratiksha"},{"ID":7,"Name":"pratikshaman"}]',
//The json array
jsonArray = JSON.parse(jsonString),
//search function to returns entry by id
jsonSearch = function(id){
return jsonArray.filter(function(obj){
return obj.ID === id;
});
};
console.log(jsonSearch(6)); //Array contains your Pratiksha object and any other matches
http://jsfiddle.net/uckpL5bt/
Related
I want to add a new field to jsonObject and this new field's name will be based on a value of another field. To be clear, this an examples of what I want to achieve.
{
"values": [
{
"id": "1",
"properties": [
{
"stat": "memory",
"data": 8
},
{
"stat": "cpu",
"data": 4
}
]
},
{
"id": "2",
"properties": [
{
"stat": "status",
"data": "OK"
},
{
"stat": "cpu",
"data": 4
}
]
}
]
}
I want to add a new field to each json object that will have the value of field "stat" as name.
{
"values": [
{
"id": "1",
"properties": [
{
"stat": "memory",
"data": 8,
"memory": 8
},
{
"stat": "cpu",
"data": 4,
"cpu": 4
}
]
},
{
"id": "2",
"properties": [
{
"stat": "status",
"data": 0,
"status": 0
},
{
"stat": "cpu",
"data": 4,
"cpu": 4
}
]
}
]
}
I have tried to do the following with JsonPath library but for me it's an ugly solution as I will parse the json three times and I do some manual replacements.
val configuration = Configuration.builder().options(Option.DEFAULT_PATH_LEAF_TO_NULL, Option.ALWAYS_RETURN_LIST).build()
val jsonContext5 = JsonPath.using(configuration).parse(jsonStr)
val listData = jsonContext.read("$['values'][*]['properties'][*]['data']").toString
.replace("[", "").replace("]", "").split(",").toList
val listStat = jsonContext.read("$['values'][*]['properties'][*]['stat']").toString
.replace("[", "").replace("]", "")
.replace("\"", "").split(",").toList
// Replacing values of "stat" by values of "data"
jsonContext5.map("$['values'][*]['properties'][*]['stat']", new MapFunction() {
var count = - 1
override def map(currentValue: Any, configuration: Configuration): AnyRef = {
count += 1
listData(count)
}
})
// replace field stat by its value
for( count <- 0 to listStat.size - 1){
val path = s"['values'][*]['properties'][$count]"
jsonContext5.renameKey(path, "stat", s"${listStat(count)}")
}
This is the result obtained
{
"values": [
{
"id": "1",
"properties": [
{
"data": 8,
"memory": "8"
},
{
"data": 4,
"cpu": "4"
}
]
},
{
"id": "2",
"properties": [
{
"data": 0,
"memory": "0"
},
{
"data": 4,
"cpu": "4"
}
]
}
]
}
Is there any better method to achieve this result ? I tried to do it with gson but it's not good handling paths.
This a way to do it with Gson but I will lose the information about other columns since I'm creating another json.
val jsonArray = jsonObject.get("properties").getAsJsonArray
val iter = jsonArray.iterator()
val agreedJson = new JsonArray()
while(iter.hasNext) {
val json = iter.next().getAsJsonObject
agreedJson.add(replaceCols(json))
}
def replaceCols(json: JsonObject) = {
val fieldName = "stat"
if(json.has(fieldName)) {
val columnName = json.get(fieldName).getAsString
val value: String = if (json.has("data")) json.get("data").getAsString else ""
json.addProperty(columnName, value)
}
json
}
How about something like this?
private static void statDup(final JSONObject o) {
if (o.containsKey("properties")) {
final JSONArray a = (JSONArray) o.get("properties");
for (final Object e : a) {
final JSONObject p = (JSONObject) e;
p.put(p.get("stat"), p.get("data"));
}
} else {
for (final Object key : o.keySet()) {
final Object value = o.get(key);
if (value instanceof JSONArray) {
for (final Object e : (JSONArray) value) {
statDup((JSONObject) e);
}
}
}
}
}
Using Gson, what you should do is create a base class that represents your initial JSON object. Then, extend that class and add the additional attribute(s) you want to add, such as "stat". Then, load the JSON objects into memory, either one by one or all together, then make the necessary changes to each to encompass your changes. Then, map those changes to the new class if you didn't in the prior step, and serialize them to a file or some other storage.
This is type-safe, a pure FP circe implementation with circe-optics:
object CirceOptics extends App {
import cats.Applicative
import cats.implicits._
import io.circe.{Error => _, _}
import io.circe.syntax._
import io.circe.parser._
import io.circe.optics.JsonPath._
val jsonStr: String = ???
def getStat(json: Json): Either[Error, String] =
root.stat.string.getOption(json)
.toRight(new Error(s"Missing stat of string type in $json"))
def getData(json: Json): Either[Error, Json] =
root.data.json.getOption(json)
.toRight(new Error(s"Missing data of json type in $json"))
def setField(json: Json, key: String, value: Json) =
root.at(key).setOption(Some(value))(json)
.toRight(new Error(s"Unable to set $key -> $value to $json"))
def modifyAllPropertiesOfAllValuesWith[F[_]: Applicative](f: Json => F[Json])(json: Json): F[Json] =
root.values.each.properties.each.json.modifyF(f)(json)
val res = for {
json <- parse(jsonStr)
modifiedJson <- modifyAllPropertiesOfAllValuesWith { j =>
for {
stat <- getStat(j)
data <- getData(j)
prop <- setField(j, stat, data)
} yield prop
} (json)
} yield modifiedJson
println(res)
}
The previous answer from Gene McCulley gives a solution with Java and using class net.minidev.json. This answer is using class Gson and written in Scala.
def statDup(o: JsonObject): JsonObject = {
if (o.has("properties")) {
val a = o.get("properties").getAsJsonArray
a.foreach { e =>
val p = e.getAsJsonObject
p.add(p.get("stat").getAsString, p.get("data"))
}
} else {
o.keySet.foreach { key =>
o.get(key) match {
case jsonArr: JsonArray =>
jsonArr.foreach { e =>
statDup(e.getAsJsonObject)
}
}
}
}
o
}
Your task is to add a new field to each record under each properties in the JSON file, make the current stat value the field name and data values the new field values. The code will be rather long if you try to do it in Java.
Suggest you using SPL, an open-source Java package to get it done. Coding will be very easy and you only need one line:
A
1
=json(json(file("data.json").read()).values.run(properties=properties.(([["stat","data"]|stat]|[~.array()|data]).record())))
SPL offers JDBC driver to be invoked by Java. Just store the above SPL script as addfield.splx and invoke it in a Java application as you call a stored procedure:
…
Class.forName("com.esproc.jdbc.InternalDriver");
con= DriverManager.getConnection("jdbc:esproc:local://");
st = con.prepareCall("call addfield()");
st.execute();
…
I am really struggling to figure something out in a piece of code I'm working on to pass through a string to multi level JSON. I know that groovy will treat example ="multi.level "$example" as one single property and I have been trying to figure out how to split the string keep the delimiter and then add it to an if statement without any success. I have looked at other solutions but am unable to get them to work in my case... Any help would be appreciated.
JSON:
scriptOutput: [
{
"id": 1,
"data": {
"name": "fyre-discard-vm-1007"
},
"key": "ABCDE123"
},
{
"id": 2,
"data": {
"name": "fyre-discard-vm-1008"
},
"key": "ABCYRE123"
},
{
"id": 3,
"data": {
"name": "fyre-discard-vm-1009"
},
"key": "AZREDE123"
},
{
"id": 4,
"data": {
"name": "fyre-discard-vm-1010"
},
"key": "YTNER857"
},
{
"id": 5,
"data": {
"name": "fyre-discard-vm-1011"
},
"key": "YANT76563A"
},
{
"id": 6,
"data": {
"name": "fyre-discard-vm-1012"
},
"key": "DYAN31685"
},
{
"id": 7,
"data": {
"name": "fyre-discard-vm-1013"
},
"key": "SANF84923"
},
{
"id": 8,
"data": {
"name": "fyre-discard-vm-1014"
},
"key": "SADNS57985"
},
{
"id": 9,
"data": {
"name": "fyre-discard-vm-1015"
},
"key": "DYUIK89OP"
},
{
"id": 10,
"data": {
"name": "fyre-discard-vm-1016"
},
"key": "DHJMNNB6547"
}
]
CODE
#!/usr/local/bin/groovy
import groovy.json.*
def proc7 = "curl https://my-json-server.typicode.com/owainow/privateAPI/machines".execute().text
def slaveList = ["fyre-discard-vm-1007","fyre-discard-vm-1015","fyre-discard-vm-1016"]
def deleteMap=[:]
def jsonName = "data.name"
println "scriptOutput: ${proc7}"
def json = new groovy.json.JsonSlurper().parseText(proc7)
for (slave in slaveList)
{
println(slave);
if (json.find{it.data.name==slave}){ //This works as the properties are passed through as properties
id = json.find{it.data.name==slave}.key
deleteMap = deleteMap+[(slave):(id)]
// I would like to do something like this however I cannot figure out how to split my properties and pass them through in a way that works
/* if (json.find{it."$jsonName"==slave}){ SOMEHOW expand or split jsonName here
id = json.find{it."$jsonName"==slave}.key
deleteMap = deleteMap+[(slave):(id)] */
println "Match"
println (id)
println deleteMap;
}
else{
println"No"
}
}
Cheers guys.
why do you need this? why jsonName should be a string?
Asking this because to get deleteMap from json is quite simple groovy expression:
def deleteMap= json.findAll{ it.data.name in slaveList }.collectEntries{ [it.id, it.data.name] }
however, if you still need it - groovy supports dynamic expression evaluation:
def jsonName = "ROOT.data.name"
def deleteMap= json.findAll{ Eval.me('ROOT', it, jsonName) in slaveList }.collectEntries{ [it.id, Eval.me('ROOT', it, jsonName)] }
I was going to suggest to use the getAt() operator
it[jsonName]
but it turns out that you have a bug in your code, apparently:
id = json.find{it."${jsonName}"==slave}.key
should be
id = json.find{it.data."${jsonName}"==slave}.key
I would still probably use
id = json.find{it.data[jsonName]==slave}.key
Here's complete, corrected snippet:
import groovy.json.*
def proc7 = "curl https://my-json-server.typicode.com/owainow/privateAPI/machines".execute().text
def slaveList = ["fyre-discard-vm-1007","fyre-discard-vm-1015","fyre-discard-vm-1016"]
def deleteMap=[:]
println "scriptOutput: ${proc7}"
def json = new groovy.json.JsonSlurper().parseText(proc7)
for (slave in slaveList)
{
println(slave);
if (json.find{it.data.name==slave}){ //This works as the properties are passed through as properties
id = json.find{it.data.name==slave}.key
deleteMap = deleteMap+[(slave):(id)]
// I would like to do something like this however I cannot figure out how to split my properties and pass them through in a way that works
/* if (json.find{it."$jsonName"==slave}){ SOMEHOW expand or split jsonName here
id = json.find{it."$jsonName"==slave}.key
deleteMap = deleteMap+[(slave):(id)] */
def jsonName="name"
id = json.find{it.data."${jsonName}"==slave}?.key
if (id) {
deleteMap = deleteMap+[(slave):(id)]
println "Match"
println (id)
println deleteMap;
}
}
else{
println"No"
}
}
I want to convert following JSON
{
"docType": {
"order": 1,
"type": "String"
},
"docNum": {
"order": 2,
"type": "String"
},
"amount": {
"order": 3,
"type": "Double"
}
}
into DTO by parsing above JSON let say
OutPutFileDTO of
private String doctype,
private String docNum,
private Double amount,
Note: order refers ordering of variables.
You are able to use Jackson( https://mkyong.com/java/jackson-how-to-parse-json/ ) of Gson( https://mkyong.com/java/how-to-parse-json-with-gson/ )
I am aware there are duplicate questions. I am not able to figure this out despite that.
Below is a JSON file which I receive from an API. I need to get the "year" value.
The error I am getting is:
message org.glassfish.jersey.server.ContainerException: org.json.JSONException: JSONArray[1] not found.
Which relates to the line on Java:
JSONObject year = years.getJSONObject(1).getJSONObject("years");
I also tried:
JSONObject year = years.getJSONObject(1);
Why is this code not working? Isn't index 1 clearly year in the years array?
JSON
{
"make": {
"id": 200000404,
"name": "Chevrolet",
"niceName": "chevrolet"
},
"model": {
"id": "Chevrolet_Camaro",
"name": "Camaro",
"niceName": "camaro"
},
"drivenWheels": "rear wheel drive",
"numOfDoors": "2",
"options": [],
"colors": [],
"manufacturerCode": "1EH67",
"price": {
"baseMSRP": 34180.0,
"baseInvoice": 32813.0,
"deliveryCharges": 900.0,
"usedTmvRetail": 17766.0,
"usedPrivateParty": 16321.0,
"usedTradeIn": 14755.0,
"estimateTmv": false,
"tmvRecommendedRating": 0
},
"categories": {
"market": "Performance",
"EPAClass": "Compact Cars",
"vehicleSize": "Midsize",
"primaryBodyType": "Car",
"vehicleStyle": "Convertible",
"vehicleType": "Car"
},
"vin": "2G1FC3D33C9165616",
"squishVin": "2G1FC3D3C9",
"years": [{
"id": 100531911,
"year": 2012,
"styles": [{
"id": 101395591,
"name": "LT 2dr Convertible w/2LT (3.6L 6cyl 6M)",
"submodel": {
"body": "Convertible",
"modelName": "Camaro Convertible",
"niceName": "convertible"
},
"trim": "LT"
}]
}],
"matchingType": "SQUISHVIN",
"MPG": {
"highway": "28",
"city": "17"
}
}
JAVA
public String vehicleData(#PathParam("vin") String vin,
#PathParam("key") String key) throws Exception {
GetVehicleJSON jsonData = new GetVehicleJSON(vin, key);
JSONObject data = jsonData.getVehicleData();
String name = data.getJSONObject("make").getString("name");
String highway = data.getJSONObject("MPG").getString("highway");
String city = data.getJSONObject("MPG").getString("city");
JSONArray years = data.getJSONArray("years");
JSONObject year = years.getJSONObject(1).getJSONObject("years");
String s = year.getString("year");
return name + " " + s + " " + highway + " " + city;
}
You're working with JSON array whose indexing is zero-based. Do it as:
JSONArray years = data.getJSONArray("years");
String year = years.getJSONObject(0).getString("year");
Your json shows that the years value is an array with 1 element and inside that element is an object:
"years": [{ "id": 100531911, "year": 2012, "styles": [{ "id": 101395591, "name": "LT 2dr Convertible w/2LT (3.6L 6cyl 6M)", "submodel": { "body": "Convertible", "modelName": "Camaro Convertible", "niceName": "convertible" }, "trim": "LT" }] }],
Because array element numbering begins at 0, that means if you select element 1 you will get this error:
message org.glassfish.jersey.server.ContainerException: org.json.JSONException: JSONArray[1] not found.
To fix it you need to select element 0 instead of 1:
years.getJSONObject(0);
I am facing the following difficulty:
I create a JSONObject.
With System.out.println (finalJson) I get the output below. It is valid JSON according to JSONLint. But when I try to get the String representationn by calling finalJson.toString (), it only returns null. How is that possible? What am I missing here?
{
"id": "cell: chris-VirtualBoxCell01",
"name": "cell: chris-VirtualBoxCell01",
"data": {},
"children": [
{
"id": "node: chris-VirtualBoxNode01",
"name": "node: chris-VirtualBoxNode01",
"data": {},
"children": [
{
"id": "applicationServer: C4Cluster_server1",
"name": "applicationServer: C4Cluster_server1",
"data": {},
"children": []
},
{
"id": "nodeAgent: nodeAgent",
"name": "nodeAgent: nodeAgent",
"data": {},
"children": []
}
]
},
{
"id": "deploymentManagerNode: chris-VirtualBoxCellManager01",
"name": "deploymentManagerNode: chris-VirtualBoxCellManager01",
"data": {},
"children": [
{
"id": "deploymentManager: deploymentManager",
"name": "deploymentManager: deploymentManager",
"data": {},
"children": []
}
]
}
]
}
Here's the snippet that should be of interest:
//Get JSON from Grails domain model
JSON json = ServerNode.findAll ("from ServerNode as s where s.root=true") as JSON;
//check result
System.out.println (json);
//turn into a JSONObject by chopping off surrounding []
String jsonString = json.toString ().substring (1, json.toString ().length ()-1);
//check result
System.out.println (jsonString);
//render to JSONObject
JSONObject jObject = new JSONObject (jsonString);
//modify structure a little more
JSONObject finalJson = modifyJson (jObject);
//check the final form (produces the above output)
System.out.println (finalJson);
//turn into string and print --> returns null
String jString = finalJson.toString ();
System.out.println (jString);