I'm trying to get the value of a specific attribute in a JSON file but instead I get a row content of the array.
For example that's my JSON file:
{
"head": {
"vars": [ "type1" , "pred" , "type2" ]
} ,
"results": {
"bindings": [
{
"type1": { "type": "Collection" } ,
"type2": { "type": "has" } ,
"type3": { "type": "contributor" }
} ,
{
"type1": { "type": "Collection2" } ,
"type2": { "type": "has2" } ,
"type3": { "type": "contributor2" }
}
]
}
}
I want to get only the values of attribute "type3"
But my following code gets me all of them.
JSONObject obj = new JSONObject(json);
JSONObject results = obj.getJSONObject("results");
JSONArray bindings = results.getJSONArray("bindings");
for (int i=0; i<bindings.length(); i++)
{
JSONObject x = bindings.getJSONObject(i);
x.getJSONObject("type3");
}
I tried several approaches but it seems I'm doing it wrong.
I only want to get this : { "type": "contributor" }
Then get that value (roughly) like so
bindings.getJSONObject(0).getJSONObject("type3")
you can use JsonPath.read to get all Type3 values as list.
List value = JsonPath.read(bindings, "..type3");
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 have received a json string like so:
{
"data": [
{
"name": "Order",
"value": "2"
},
{
"name": "Address",
"value": "182"
},
{
"name": "DNS",
"value": "null"
},
{
"name": "SSID",
"value": "work"
},
{
"name": "Protocol",
"value": "0"
},
{
"name": "Key",
"value": ""
},
{
"name": "carrier",
"value": "undefined"
},
{
"name": "SSH",
"value": "1"
},
{
"name": "ntp_addr",
"value": ""
},
{
"name": "Name",
"value": ""
}
]
}
I used stringify on an html response and this is what I have to parse. As you can see, it is pretty redundant; I would much rather { "Order":"2" } than { "name":"Order","value":"2" } ... So an array of name-value pairs, instead of an array of objects.
Is there a way I can dynamically format this response so that it will be easier to parse?
What 'd like is to be able to say:
JSONObject jsonObject = new JSONObject(jsonResponse);
JSONArray data = jsonObject.getJSONArray("data");
for (int i = 0; i < data.length(); i++) {
JSONObject dataObject = data.getJSONObject(i);
String order = dataObject.getString("Order");
String address = dataObject.getString("Address");
// etc...
}
But the current format makes it almost impossible to parse. I'd need loops within loops.
I'd like to use com.google.gson library. And this response easy to parse with it:
private final JsonParser PARSER = new JsonParser();
public void parse(String jsonString) {
JsonObject dataObject = PARSER.parse(jsonString).getAsJsonObject();
JsonArray dataArray = dataObject.get("data").getAsJsonArray();
dataArray.iterator().forEachRemaining(element -> {
String name = element.getAsJsonObject().get("name").getAsString();
String value = element.getAsJsonObject().get("value").getAsString();
}
}
Or you can simply use TypeAdapters for json deserialization directly in the object.
Something like this should do the trick
JSONObject jsonObject = new JSONObject(jsonResponse);
JSONArray data = jsonObject.getJSONArray("data");
JSONObject simplifiedDataObject = new JSONObject();
for (int i = 0; i < data.length(); i++) {
JSONObject dataField = data.getJSONObject(i);
simplifiedDataObject.put(dataField.getString("name"), dataField.get("value"));
}
You just iterate over each element in data, use the name field as the field on a new JSONObject and simply retrieve the value using the value key.
I need to iterate and get the last values like name, url and color from below JSON response. Using java/gson api. Please help me on this.
{
"Title": {
"desc": [
{
"name": "PRE_DB",
"url": "http://jenkins.example.com/job/my_first_job/",
"color": "blue_anime"
},
{
"name": "SDD_Seller_Dashboard",
"url": "http://jenkins.example.com/job/my_second_job/",
"color": "blue_anime"
}
]
}
}
example output :
name : SDD_Seller_Dashboard
color :blue_anime
JSONObject data = new JSONObject(your_JSON_Repsonse);
JSONArray data_desc=data.getJSONArray(desc);
for(int i=0;i<=data_desc.length();i++)
{
name=data_desc.getString("name");
url=data_desc.getString("url");
color=data_desc.getString("color");
}
I have the following HTTP JSON-response in Java, which represents a user object.
{
"account": "Kpatrick",
"firstname": "Patrick",
[
],
"instances":
[
{
"id": "packerer-pool",
"key": "packerer-pool123",
"userAccount": "kpatrick",
"firstname": "Patrick",
"lastname": "Schmidt",
}
],
"projects":
[
{
"id": "packerer-projectPool",
"projectKey": "projectPool-Pool",
"cqprojectName": "xxxxx",
},
{
"id": "packerer-secondproject",
"projectKey": "projectPool-Pool2",
"cqprojectName": "xxxx",
},
{
"id": "packerer-thirdproject",
"projectKey": "projectPool-Pool3",
"cqprojectName": "xxxx",
}
],
"clients":
[
],
"dbid": 76864576,
"version": 1,
"id": "dbpack21"
}
Now, I want to search a specific project with the help of the projectkey (for example "projectPool-Pool2"). After that, I want to delete the element completely. Because my target is to send a HTTP post-call without this project.
The result should be similar to below for my HTTP post-call:
{
"account": "Kpatrick",
"firstname": "Patrick",
[
],
"instances":
[
{
"id": "packerer-pool",
"key": "packerer-pool123",
"userAccount": "kpatrick",
"firstname": "Patrick",
"lastname": "Schmidt",
}
],
"projects":
[
{
"id": "packerer-projectPool",
"projectKey": "projectPool-Pool",
"cqprojectName": "xxxxx",
},
{
"id": "packerer-thirdproject",
"projectKey": "projectPool-Pool3",
"cqprojectName": "xxxx",
}
],
"clients":
[
],
"dbid": 76864576,
"version": 1,
"id": "dbpack21"
}
First i have parsed the response to a string.
private static String getContent(HttpResponse response) {
HttpEntity entity = response.getEntity();
if (entity == null) return null;
BufferedReader reader;
try {
reader = new BufferedReader(new InputStreamReader(entity.getContent()));
String line = reader.readLine();
reader.close();
return line;
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
And now i am trying to search the specific project, but i don't know how to continue.
String StringResponse = getContent(JsonResponse);
JSONObject jsonObject = new JSONObject(StringResponse);
JSONArray ProjectsArray= jsonObject.getJSONArray("projects");
Is that approach correct?
Best Regards!
Once you have your array, try something like...
// Array to store the indexes of the JSONArray to remove
ArrayList<Integer> indexesToRemove = new ArrayList<Integer>();
// Iterate through projects array, check the object at each position
// if it contains the string you want, add its index to the removal list
for (int i = 0; i < projectsArray.length; i++) {
JSONObject current = projectsArray.get(i);
if (current.get("projectKey") == "**DESIRED PROJECT KEY**") {
indexesToRemove.add(i);
}
}
Now you can iterate through your indexes to remove, and remove the corresponding object from the array with the JSONArrays remove method (not sure what it is called, the code above is from memory). Make sure to remove your items BACKWARDS, otherwise you will delete earlier items, which will change the indexes, resulting in your removing an incorrect item if you then remove another index.
// Going through the list backwards so we can remove the highest item each
//time without affecting the lower items
for (int i = indexesToRemove.size()-1; i>=0; i--) {
projectsArray.remove(indexesToRemove.get(i));
}
I have a JSON string and I am trying to retrieve information from it. Json String looks like this.
JSON STRING :
{
"information": {
"device": {
"id": 0
},
"user": {
"id": 0
},
"data": [
{
"datum": {
"id": "00GF001",
"history_id": "9992BH",
"name": "abc",
"marks": 57,
"class": "B",
"type": "Student"
}
},
{
"datum": {
"id": "72BA9585",
"history_id": "78NAH2",
"name": "ndnmanet",
"marks": 70,
"class": "B",
"type": "Student"
}
},
{
"datum": {
"id": "69AHH85",
"history_id": "NN00E3006",
"name": "kit",
"department": "EF003",
"class": "A",
"type": "Employee"
}
},
{
"datum": {
"id": "09HL543",
"history_id": "34QWFTA",
"name": "jeff",
"department": "BH004",
"class": "A1",
"type": "Employee_HR"
}
}
]
}
}
I am trying to access data JSONArray and respective Datum from it. I differentiated each datum as per type such as student, employee etc and push information in hashmap.
I successfully did it in javascript but in Java I am struggle abit.
When I am trying to access JSONArray it throws exception
try {
JSONObject data = new JSONObject(dataInfo);
// Log.d(TAG, "CHECK"+data.toString());
JSONObject info = data.optJSONObject("information");
if(info.getJSONArray("data").getString(0).equals("Student") > 0) //exception here
Log.d(TAG, "Data"+ data.getJSONArray("data").length()); //exception here too
for(int m = 0; m < data.length(); m++){
// for(int s = 0; s < data[m].ge)
}
} catch (JSONException j){
j.printStackTrace();
}
Any pointers to create hashmap respective type I have. Appreciated
If you're trying to access the type field of a datum object, you'll want something like this:
JSONObject data = new JSONObject(dataInfo); // get the entire JSON into an object
JSONObject info = data.getJSONObject("information"); // get the 'information' object
JSONArray dataArray = info.getJSONArray("data"); // get the 'data' array
for (int i = 0; i < dataArray.length(); i++) {
// foreach element in the 'data' array
JSONObject dataObj = dataArray.getJSONObject(i); // get the object from the array
JSONObject datum = dataObj.getJSONObject("datum"); // get the 'datum' object
String type = datum.getString("type"); // get the 'type' string
if ("Student".equals(type)) {
// do your processing for 'Student' here
}
}
Note that you'll have to deal with exception handling, bad data, etc. This code just shows you the basics of how to get at the data that you're looking for. I separated each individual step into its own line of code so that I could clearly comment what is happening at each step, but you could combine some of the steps into a single line of code if that is easier for you.
if dataInfo is the json you posted, then you have to access information and from information, you can access data:
JSONObject data = new JSONObject(dataInfo);
JSONObject info = data.optJSONObject("information");
if (info != null) {
JSONArray dataArray = info.optJSONArray("data")
}