Can anyone help me? How to convert the below Input to JSON Object?
Input :
{ "details": { "device/0/endPointClientName": "ndm-xx-1", "device/1/endPointClientName": "ndm-xx-2", "EnergyMeter/0/current": "20", "EnergyMeter/0/total": "400", } }
Output:-
{ "device": [ {"endPointClientName":"ndm-xx-1" }, {"endPointClientName":"ndm-xx-2" } ], "EnergyMeter": [ {"current":"20", "total":"400"} ] }
I have the Input as JSON Object with Properties class. In the Input we are sharing the FULL PATH. we have to convert this to JSON Object.
[demo]https://jsfiddle.net/CntChen/vh7kat5a/
var input = {
"details": {
"device/0/endPointClientName": "ndm-xx-1",
"device/1/endPointClientName": "ndm-xx-2",
"EnergyMeter/0/current": "20",
"EnergyMeter/0/total": "400",
}
};
function decodeFlatObj(flatOjb) {
var outputObj = {};
for (var key in flatOjb) {
var objNow = outputObj;
var subkey = key.split('/');
for (var i = 0; i < subkey.length - 1; i++) {
// next subkey is number
if (/\d|[1-9]\d*/.test(subkey[i + 1])) {
// current subkey is number
if (/\d|[1-9]\d*/.test(subkey[i])) {
objNow.push([]);
objNow = objNow[parseInt(subkey[i])];
} else {
objNow[subkey[i]] = objNow[subkey[i]] || [];
objNow = objNow[subkey[i]];
}
} else { // next subkey is object
// current subkey is number
if (/\d|[1-9]\d*/.test(subkey[i])) {
objNow[parseInt(subkey[i])] = objNow[parseInt(subkey[i])] || {};
objNow = objNow[parseInt(subkey[i])];
} else {
objNow[subkey[i]] = objNow[subkey[i]] || {};
objNow = objNow[subkey[i]];
}
}
}
var valueDecode;
if (typeof flatOjb[key] === 'object') {
valueDecode = decodeFlatObj(flatOjb[key]);
} else {
valueDecode = flatOjb[key];
}
if (/\d|[1-9]\d*/.test(subkey[subkey.length - 1])) {
objNow[parseInt(subkey[subkey.length - 1])].push(valueDecode);
} else {
objNow[subkey[subkey.length - 1]] = valueDecode;
}
}
return outputObj;
}
var output = decodeFlatObj(input);
console.log(input);
console.log(JSON.stringify(output));
//{"details":{"device":[{"endPointClientName":"ndm-xx-1"},{"endPointClientName":"ndm-xx-2"}],"EnergyMeter":[{"current":"20","total":"400"}]}}
Related
I was given a String in java method and have to return the son depth of that string
like if the method is
find depthJSON(String s){
//code
return count;
}
for example:
{
"0" : { "name" : "John", "City" : "NY"},
"1" : { "name" : "Mike", "City" : "LA"}
}
for this input, depth is 2
Your problem calls for a JSON Tokenizer. You do not actually need to parse your file ( ie. build some tree structure as a Java object ) as you are only interested in the maximal nesting depth which can be deduced from the token stream alone.
The basic idea is to keep tabs on the tokens that represent the start and end of an object ( {, } ). Whenever the tokenizer sees an object start/end, increment/decrement a global depth counter; Whenever the tokenizer sees an object end, check whether the current global depth counter is greater than the maximum seen so far and change the value accordingly.
As a package to furnish the JSON Tokenizer, I'd suggest Jackson. Download the jar files into your source directory (or to the suitable place in your development toolset directory). The jar files are available at:
https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-core/2.10.3/jackson-core-2.10.3.jar
https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.10.3/jackson-annotations-2.10.3.jar
https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.10.3/jackson-databind-2.10.3.jar
Note that you need all of them and do not forget to alter the Java CLASSPATH unless your IDE takes care of that.
Code
The following class determines and prints the depth of your json:
// https://stackoverflow.com/questions/61097605/finding-the-depth-of-a-json-string-in-java
//
// javac.exe -cp "./jackson-core-2.10.3.jar;./jackson-annotations-2.10.3.jar;./jackson-databind-2.10.3.jar" .\json_nesting.java
// java.exe -cp "./jackson-core-2.10.3.jar;./jackson-annotations-2.10.3.jar;./jackson-databind-2.10.3.jar;." json_nesting
//
// Cf. https://github.com/FasterXML/jackson-databind#5-minute-tutorial-streaming-parser-generator
//
// Jar downloads
// https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-core/2.10.3/jackson-core-2.10.3.jar
// https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.10.3/jackson-annotations-2.10.3.jar
// https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.10.3/jackson-databind-2.10.3.jar
//
import java.lang.*;
import java.io.*;
import java.nio.*;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.ObjectMapper;
public class json_nesting {
public static void main(String[] args) {
// write your code here
// Second: read file back
String fpath = "<file path goes here>"; // Double backslashes on Windows !
ObjectMapper mapper = new ObjectMapper(); // create once, reuse
JsonFactory f = mapper.getFactory();
try {
JsonParser p = f.createParser(new File(fpath));
JsonToken t = p.nextToken();
int currentDepth = 0;
int maxDepth = 0;
while (t != null) {
if (t == JsonToken.START_OBJECT) {
currentDepth++;
} else {
if (t == JsonToken.END_OBJECT) {
if (currentDepth > maxDepth) {
maxDepth = currentDepth;
}
currentDepth--;
}
}
t = p.nextToken();
};
System.out.printf("Max depth = %4d.\n", maxDepth);
p.close();
} catch ( IOException ioe ) {
System.out.printf("File processing failed: = '%s'. Message: %s.\n", fpath, ioe.getMessage());
}
}
}
Tested with Java SE 11, u 28.
Note (JSON syntax)
Note that your sample file is NOT valid JSON - some property names are not enclosed in double quotes, properties are not separated with commas. A rectified version comes here:
{
"0" : { "name" : "John", "City" : "NY"}
, "1" : { "name" : "Mike", "City" : "LA"}
}
public static int levelCount(String word) {
int current= 0;
int max = 0;
for (int i = 0; i < word.length(); i++) {
if (word.charAt(i) == '{') {
current++;
} else {
if (word.charAt(i) == '}') {
if (current > max) {
max = current;
}
current--;
}
}
}
return max;
}
my answer is
int JsonDepth (String S) {
int current_max = 0;
int max = 0;
int n = S.length();
for (int i = 0; i < n; i++) {
if (S.charAt(i) == '{') {
current_max++;
// update max if required
if (current_max > max) {
max = current_max;
}
} else if (S.charAt(i) == '}') {
if (current_max > 0) {
current_max--;
} else {
return -1;
}
}
}
if (current_max != 0) {
return -1;
}
return max;
}
I have a lot of JSON files in the following format. I want to map one attribute named Timings to integer.
test.json
"Rating": {
"ratingValue": "4.636365",
"bestRating": "5",
"worstRating": "1",
"ratingCount": "66"
},
"Timings": {
"cookTime": "PT1H",
"prepTime": "PT10M",
"totalTime": "PT1H10M"
}
I want to store the output in another JSON file after mapping. Let say, totalTime in Timings is 1H10M then we assign this as "totalTime:7". If its, "30M" we can assign this as "totalTime:3". I want to do this using java.
Required output
"Rating":
{
"ratingValue": "4.636365",
},
"Timings":
{
"totalTime": "7"
}
I tried this :
class Timings {
private String cookTime;
private String prepTime;
private String totalTime;
public String getCookTime() {
return cookTime;
}
public void setCookTime(String cookTime) {
this.cookTime = cookTime;
}
public String getPrepTime() {
return prepTime;
}
public void setPrepTime(String prepTime) {
this.prepTime = prepTime;
}
public String getTotalTime() {
return totalTime;
}
public void setTotalTime(String totalTime) {
this.totalTime = totalTime;
}
#Override
public String toString() {
return "Timings [cookTime=" + cookTime + ", prepTime=" + prepTime + ", totalTime=" + totalTime + "]";
}
}
public class Test {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
Timings obj = mapper.readValue(new File("C:\\Users\\Anish\\Desktop\\abc.json"), Timings.class);
String totalTime = obj.getTotalTime().split("PT")[1];
int total = 0;
if (totalTime != null && !totalTime.isEmpty()) {
total = returnTotalTime(totalTime);
}
ObjectNode mainNode = mapper.createObjectNode();
ObjectNode timingNode = mapper.createObjectNode();
childNode.put("totalTime", (total > 9) ? (total / 10) : total);
mainNode.set("Timings", timingNode);
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(mainNode);
System.out.println(json);
}
private static int returnTotalTime(String totalTime) {
if (totalTime != null && !totalTime.isEmpty()) {
String[] timeValues = totalTime.split("H");
if (timeValues.length == 0) {
return 0;
} else if (timeValues.length < 2) {
if (timeValues[0].contains("M")) {
return (timeValues[0].split("M").length <= 0) ? 0
: timeValues[0].split("M")[0].isEmpty() ? 0 : Integer.parseInt(timeValues[0].split("M")[0]);
}
return timeValues[0].isEmpty() ? 0 : Integer.parseInt(timeValues[0]) * 60;
}
int hour = timeValues[0].isEmpty() ? 0 : Integer.parseInt(timeValues[0]) * 60;
int mins = (timeValues[1].split("M").length <= 0) ? 0
: timeValues[1].split("M")[0].isEmpty() ? 0 : Integer.parseInt(timeValues[1].split("M")[0]);
return (hour + mins);
}
return 0;
}
abc.json
{
"cookTime": "PT1H",
"prepTime": "PT10M",
"totalTime": "PT1H10M"
}
Output :
{
"Timings" : {
"totalTime" : "7"
}
}
When "totalTime": "PT30M", then :
Output :
{
"Timings" : {
"totalTime" : "3"
}
}
When "totalTime": "PT23M", then :
Output :
{
"Timings" : {
"totalTime" : "2"
}
}
You can use any library to parse Json data depending of your goals.
for example org.json is a good choice and here is an example:
JSONObject object = new JSONObject(stringData);
String time = object.getJSONObject("Timings").getString("cookTime");
this way you can parse every Json data and do your business after that.
Also you can use mapping your data to a class with gson or other tools.
I have mList2 with values. There are values with the same id. How can I get a List or ArrayList in which objects with the same id are grouped and add it to ArrayList>?
List<ProfileActivity.DataPost> mList2 = list;
List<List<ProfileActivity.DataPost>> output = new ArrayList<List<ProfileActivity.DataPost>>();
List<ProfileActivity.DataPost> itemsAlreadyGrouped = new ArrayList<ProfileActivity.DataPost>();
for (int i = 0; i < mList2.size(); i++) {
List<ProfileActivity.DataPost> groupList = new ArrayList<ProfileActivity.DataPost>();
boolean groupCandidateFound = false;
if (!itemsAlreadyGrouped.contains(mList2.get(i))) {
for (int j = 0; j < mList2.size(); j++) {
if (mList2.get(i).getIds_post().equals(mList2.get(j).getIds_post())) {
groupList.add(mList2.get(i));
groupCandidateFound = true;
}
}
if (groupCandidateFound) {
itemsAlreadyGrouped.add(mList2.get(i));
}
}
if (groupList.size() > 0) {
output.add(groupList);
}
}
//Let's test the logic
for (List<ProfileActivity.DataPost> group : output) {
System.out.println(group);
Toast.makeText(context, group.toString(),Toast.LENGTH_SHORT ).show();
}
DataPost
data class DataPost(var text:String? = null, var photo:String? = null,
var type:String = "",
var ids_post:String = "", var position:String? = null)
Make your ProfileActivity.DataPost class implements Comparable<ProfileActivity.DataPost> interface, the implement the compareTo(ProfileActivity.DataPost o) method
#Override
public void compareTo(ProfileActivity.DataPost o){
return getIds_post().compareTo(o.getIds_post());
}
Then just invoke Collections.sort(list)
public Dictionary<string, SomeObject> DictionaryVar= new Dictionary<string, SomeObject>();
foreach (SomeObject ojv in DictionaryVar.Values)
{
if (dt.Rows.Find(obj.FirstName()) == null)
{
dt.Rows.Add(new object[] { false, obj.FirstName(), "", "", 0 });
}
}
I have tried this but its not working.. I am trying to populate jtable by looping through some objects by checking whether the field exists if it doesn't , then i add it to the table.
for (SomeObject bs : DictionaryVar.values()) {
System.out.println("not getting inside");
for (int i = 0; i < jTable1.getRowCount(); i++) {
if (!jTable1.getValueAt(i, 1).equals(bs.FirstName())) {
((DefaultTableModel) jTable1.getModel()).addRow(new Object[]{false, bs.FirstName(), "", "", 0, ""});
} else {
}
}
}
System.out.println("the program is outputing this");
if (ListBookMark.size() > 0) {
for (SomeObject bs : DictionaryVar.values()) {
System.out.println("working now");
if (jTable1.getModel().getColumnName(1).equalsIgnoreCase(bs.GetName()) == false) {
((DefaultTableModel) jTable1.getModel()).addRow(new Object[]{false, bs.GetName(), "", "", 0, ""});
}
}
}else {
System.out.println("bs size = " + (ListBookMark.size() ));
}
I could not find out how to traverse a JSON-tree (nested structure) and decide on the keys of the elements what to expect next and traverse from node to node. Like this (pseudocode):
int traverse(node) {
if (node.key == ADD) {
int res = 0;
for (child:node.children)
res = res + traverse(child);
}
if (node.key == "ADD") {
int res = 0;
for (child:node.children)
res = res + traverse(children);
}
if (node.key == "MULT") {
int res = 0;
for (child:node.children)
res = res * traverse(children);
}
if (node.key == "INT")
return node.value;
}
The json-string to parse could be like this:
{"ADD":[{"INT":"1"},{"INT":"3"},{"INT":"4"}]}
or this:
{"ADD":[{"INT":"1"},{"INT":"3"},{"ADD":[{"INT":"5"},{"INT":"6"}]},
{"INT":"4"}]}
How could I use JSON-Object or JSON-Arrays and
inside the objects access the key and value variables to traverse through this tree recursively?
EDITED:
After all the comments I try to put this as first running example
(still looks a little uneasy to me, but it works):
public static int evaluate(javax.json.JsonObject node) {
Set<?> keySet = node.keySet();
Iterator<?> i = keySet.iterator();
if (i.hasNext()) {
String key = i.next().toString();
System.out.println("key: " + key);
if (key.equals("ADD")) {
JsonArray ja = node.getJsonArray("ADD");
int res = 0;
for (JsonValue jvx: ja) {
if (jvx.getValueType().toString().equals("OBJECT")) {
res = res + evaluate((JsonObject)jvx);
} else{
System.err.println("jvx should not be a " + jvx.getValueType().toString() + " here");
}
}
return res;
}
if (key.equals("MULT")) {
JsonArray ja = node.getJsonArray("MULT");
int res = 1;
for (JsonValue jvx: ja) {
if (jvx.getValueType().toString().equals("OBJECT")) {
res = res * evaluate((JsonObject)jvx);
} else{
System.err.println("jvx should not be a " + jvx.getValueType().toString() + " here");
}
}
return res;
}
if (key.equals("INT")) {
String intStr = node.getString("INT");
System.out.println ("found int = " + intStr);
return Integer.parseInt(intStr);
}
}
return 0;
}
public static void readJSON() {
String jsonText = "{\"ADD\":[{\"INT\":\"1\"},{\"INT\":\"3\"},{\"ADD\":[{\"INT\":\"5\"},{\"INT\":\"6\"}]},{\"INT\":\"4\"}]}";
JsonReader reader = Json.createReader(new StringReader(jsonText));
JsonObject obj = reader.readObject();
reader.close();
int res = evaluate(obj);
System.out.println("res: " + res);
}
Your evaluating pseudocode is OK (just pay attention to the initial value when multiplying!). To adapt it to the javax.json hierarchy, you should code your evaluating method like this:
int evaluate(javax.json.JsonObject node):
Get each on of the admitted keys (ADD, MULT, INT, etc) through node.getJsonObject(key): In case it returns null, check the next admitted key, and stop at the first you find.
On each operation, a proper logic must be coded:
In case the key is a constant value (INT), return its value immediately.
In case the key is an operation, check the value's type (through node.getValueType()): If it is a single value, return it as is. If it is an array, iterate through its elements and call evaluate for each one of them, and perform the proper operation with the returned value (adding, multiplying, etc). Last, return the computation's result.
After your first edit
Your first real approach looks OK; I'd just suggest you some improvements to make the code more readable:
Use an enhanced for.
Replace the if-else chanin by a switch.
Replace each case by a call to a private method.
int result;
Set<String> keySet = node.keySet();
for (String key : keySet)
{
switch (key)
{
case "ADD":
result=evaluateAdd(node.getJsonArray("ADD"));
break;
case "MULT":
result=evaluateMult(node.getJsonArray("ADD"));
break;
case "INT":
result=node.getInt("INT");
break;
...
}
}
JSON [{
"name": "com",
"children": [
{
"name": "project",
"children": [
{
"name": "server"
},
{
"name": "client",
"children": [
{
"name": "util"
}
]
}
]
}
]
}]
Try this:
public static JSONArray getNames(JSONArray inputArray, JSONArray outputArray) {
for (int i = 0; i < inputArray.length(); i++) {
JSONObject inputObject = inputArray.getJSONObject(i);
JSONObject outputObject = new JSONObject();
outputObject.put("name", inputObject.getString("name"));
outputArray.put(outputObject);
if (inputObject.has("children")) {
JSONArray children = inputObject.getJSONArray("children");
getNames(children, outputArray);
}
}
return outputArray;
}