I am printing a value in a file i need to split them onces the first content is finished leave some spaces and then print the next one
public class Test_Json {
public static ArrayList<Object> ls1 = new ArrayList<Object>();
public static ArrayList<Object> ls2 = new ArrayList<Object>();
public static void main(String[] args) throws Exception {
JsonParser parser = new JsonParser();
BufferedWriter bw = null;
FileWriter fw = null;
try {
Gson g = new Gson();
JsonElement jsonElement1 = parser.parse(new FileReader("D://sample1.json"));
JsonElement jsonElement2 = parser.parse(new FileReader("D://sample2.json"));
// System.out.println("Is the two JSON File Same: "+compareJson(jsonElement1,jsonElement2));
if (!compareJson(jsonElement1, jsonElement2)) {
Type mapType = new TypeToken<Map<String, Object>>() {
}.getType();
Map<String, Object> firstMap = g
.fromJson(jsonElement1, mapType);
Map<String, Object> secondMap = g.fromJson(jsonElement2,
mapType);
System.out.println(" The Two JSON Files Are Not the Same ");
System.out.println(Maps.difference(firstMap, secondMap));
String s = Maps.difference(firstMap, secondMap).toString();
try{
fw = new FileWriter("D:\\output.txt");
bw = new BufferedWriter(fw);
bw.write(s);
}catch(Exception e){
e.printStackTrace();
}
} else {
System.out.println("The Two JSON Are SAME!!!!!!!!!!!!!!!");
}
} catch (Exception e1) {
e1.printStackTrace();
}
}
public static boolean compareJson(JsonElement json1, JsonElement json2) {
boolean isEqual = true;
if (json1 != null && json2 != null) {
if (json1.isJsonObject() && json2.isJsonObject()) {
Set<Entry<String, JsonElement>> ens1 = ((JsonObject) json1)
.entrySet();
Set<Entry<String, JsonElement>> ens2 = ((JsonObject) json2)
.entrySet();
JsonObject json2obj = (JsonObject) json2;
if (ens1 != null && ens2 != null
&& (ens2.size() == ens1.size())) {
for (Entry<String, JsonElement> en : ens1) {
isEqual = isEqual
&& compareJson(en.getValue(),
json2obj.get(en.getKey()));
}
} else {
return false;
}
}
else if (json1.isJsonArray() && json2.isJsonArray()) {
JsonArray jarr1 = json1.getAsJsonArray();
JsonArray jarr2 = json2.getAsJsonArray();
if (jarr1.size() != jarr2.size()) {
return false;
} else {
int i = 0;
for (JsonElement je : jarr1) {
isEqual = isEqual && compareJson(je, jarr2.get(i));
i++;
}
if (isEqual) {
ls1.toArray();
ls2.toArray();
isEqual = ls1.containsAll(ls2);
}
}
}
else if (json1.isJsonNull() && json2.isJsonNull()) {
return true;
}
else if (json1.isJsonPrimitive() && json2.isJsonPrimitive()) {
ls1.add(json1);
ls2.add(json2);
return true;
}
else if((json1.isJsonPrimitive() & json2.isJsonArray()) || (json2.isJsonPrimitive() && json1.isJsonArray())){
return false;
}
} else if (json1 == null && json2 == null) {
return true;
} else {
return false;
}
return isEqual;
}
}
Map.difference method gets the difference form the two file and prints them. I need to first print first file difference and then leave some lines of space and print the next file difference. This i am doing to show the contents seperately. At present it is displaying without any spaces so identifying is difficult.
I need something like this
Difference values in first file:
{
"id": 1,
"name": "A green door",
"price": 12.50,
"tags": ["home", "green"]
}
Difference in second file:
{
"id": 14,
"name": "A green door bell",
"price": 127.50,
"tags": ["home", "green"]
}
The method entriesOnlyOnLeft() and entriesOnlyOnRight() is not displaying the differece as the key should be different but here the key are same
If you want to print the map differences with a separation between the left and right sides, you can get them separately from the MapDifference result:
MapDifference diff = Maps.difference(firstMap, secondMap);
bw.write("Only on left: " + diff.entriesOnlyOnLeft());
// add separation
bw.write("Only on right: " + diff.entriesOnlyOnRight());
To include the value differences:
bw.write("Value differences: " + diff.entriesDiffering());
Related
Using PDFBox, given data notated like this: [G]Glory be to [D]God [Em]the [C]Father,\n[G]And to [A]Christ the [D]Son,, I am creating a guitar chord sheet like this:
My approach was to iterate through each character in the song and check the current index against the map.. whenever the map has an entry to that character index, we "jump" to the line above, write the chord, then jump back down.
The method setTextRise looked promising, but still processes the horizontal spacing incorrectly:
Here's an SSCCE (needs PDFBox libraries) that produces the PDF above:
public static void main(String[] args) {
try {
String extracted_text = "Capo 1\n\n1\n[G]Glory be to [D]God [Em]the [C]Father,\n[G]And to [A]Christ the [D]Son,\n[B7]Glory to the [Em]Holy [C]Spirit—\n[D-D7]Ever [ G]One.\n\n2\nAs we view the vast creation,\nPlanned with wondrous skill,\nSo our hearts would move to worship,\nAnd be still.\n\n3\nBut, our God, how great Thy yearning\nTo have sons who love\nIn the Son e’en now to praise Thee,\nLove to prove!\n\n4\n’Twas Thy thought in revelation,\nTo present to men\nSecrets of Thine own affections,\nTheirs to win.\n\n5\nSo in Christ, through His redemption\n(Vanquished evil powers!)\nThou hast brought, in new creation,\nWorshippers!\n\n6\nGlory be to God the Father,\nAnd to Christ the Son,\nGlory to the Holy Spirit—\nEver One.\n".replaceAll("\n", "\r");
String[] lines = extracted_text.split("\\r");
ArrayList<SongLine> songlines = new ArrayList<>();
for(String s : lines) {
LinkedHashMap<Integer, String> chords = new LinkedHashMap();
StringBuilder line = new StringBuilder();
StringBuilder currentchord = null;
int index = 0;
for(char c : s.toCharArray()) {
if(currentchord != null) {
if(c == ']') {
chords.put(index, currentchord.toString());
currentchord = null;
} else {
currentchord.append(c);
}
} else {
if(c == '[') {
currentchord = new StringBuilder();
} else {
line.append(c);
index++;
}
}
}
SongLine sl = new SongLine();
if(chords.size() > 0)
sl.char_index_to_chords = chords;
sl.line = line.toString();
songlines.add(sl);
}
try (PDDocument doc = new PDDocument()) {
PDPage page = new PDPage();
PDPageContentStream pcs = new PDPageContentStream(doc, page);
int firstLineX = 25;
int firstLineY = 700;
boolean first = true;
float leading = 14.5f;
pcs.beginText();
pcs.newLineAtOffset(firstLineX, firstLineY);
pcs.setFont(PDType1Font.TIMES_ROMAN, 12);
pcs.setLeading(leading);
for(SongLine line : songlines) {
if(line.char_index_to_chords != null)
System.out.println(line.char_index_to_chords.toString());
System.out.println(line.line);
if(!first) {
pcs.newLine();
}
first = false;
if(line.char_index_to_chords != null) {
pcs.newLine();
}
for(int i = 0; i < line.line.length(); i++) {
pcs.showText(String.valueOf(line.line.charAt(i)));
if(line.char_index_to_chords != null && line.char_index_to_chords.containsKey(i)) {
pcs.setTextRise(12);
pcs.showText(line.char_index_to_chords.get(i));
pcs.setTextRise(0);
}
}
}
pcs.endText();
pcs.close();
doc.addPage(page);
String path = "0001.pdf";
doc.save(path);
Desktop.getDesktop().open(new File(path));
}
} catch (Exception e) {
e.printStackTrace();
}
}
static class SongLine {
Map<Integer, String> char_index_to_chords;
String line;
}
What would you do in PDFBox to create the text aligned with chords (like in the first image)?
I got it. The answer was not setTextRise, rather newLineAtOffset while using getStringWidth to calculate font size:
for(SongLine line : songlines) {
if(!first) {
pcs.newLine();
}
first = false;
if(line.char_index_to_chords != null) {
float offset = 0;
for(Entry<Integer, String> entry : line.char_index_to_chords.entrySet()) {
float offsetX = font.getStringWidth(line.char_index_to_leading_lyrics.get(entry.getKey())) / (float)1000 * fontSize;
pcs.newLineAtOffset(offsetX, 0);
offset += offsetX;
pcs.showText(entry.getValue());
}
pcs.newLineAtOffset(-offset, -leading);
}
pcs.showText(line.line);
}
I have tried the following example.
public static void operate2(JsonElement jsonElement, List keys, JsonElement jsonElement2, String prefix){
String prefixnew = "";
if(jsonElement.isJsonArray()){
JsonArray jsonArray = jsonElement.getAsJsonArray();
for(int i=0; i<jsonArray.size(); i++){
jsonElement = jsonArray.get(i);
operate2(jsonElement, keys, jsonElement2, prefix);
}
}else if(jsonElement.isJsonObject()){
JsonObject jsonObject = jsonElement.getAsJsonObject();
Set<Map.Entry<String,JsonElement>> childEntrySet = jsonObject.entrySet();
for (Map.Entry<String, JsonElement> child: childEntrySet) {
jsonElement2 = child.getValue();
Object keyCheck = new Gson().fromJson(jsonElement2.toString(), Object.class);
if (keyCheck instanceof Map) {
prefix += child.getKey()+"_";
keys.add(prefix);
System.out.println("Map="+child.getKey());
}else if (keyCheck instanceof Collection) {
if(!prefix.equals("")){
prefix += child.getKey()+"_";
keys.add(prefix);
}else{
prefix = child.getKey()+"_";
keys.add(prefix);
}
System.out.println("Collection="+child.getKey());
}else{
prefix += "";
}
operate2(jsonElement2, keys, jsonElement2, prefix);
}
}else{
prefix = "";
}
}
public static void test2(String json){
JsonElement jsonElement = new JsonParser().parse(json);
JsonElement jsonElement2 = null;
String prefix = "";
List keys = new ArrayList();
operate2(jsonElement, keys, jsonElement2, prefix);
Set keySet = new HashSet(keys);
System.out.println("Keys = "+keys);
}
The output I got Keys = [items_, items_contact_, items_contact_records_, items_contact_records_recordings_, items_contact2_]
But I need items_, items_contact_, items_records_ .... As we can see that record is not the child of the contact, so items_contact_records_ should not be there. Instead items_records_ should be.
The source json would be
{
"items": [{
"id": 633706061003,
"fromNumber": "16572307534",
"contact": {
"id": 499354453003,
"homePhone": "16572307534"
},
"records": [{
"id": 353389055003,
"result": "LA",
"recordings": [{
"id": 16427622003
}]
}]
}],
"limit": 100,
"offset": 0,
"totalCount": 5949
}
I would use the following approach:
if the root element is not a json object, return an empty list
otherwise iterate other its entries, and for each one add the key if the value associated with is either an object or an array
proceed recursively for the value
public static List<String> operate(final JsonElement jsonElement, final String prefix, final boolean firstLayer) {
if(jsonElement.isJsonObject() || (!firstLayer && jsonElement.isJsonArray())) {
List<String> keys = new ArrayList<>();
if(jsonElement.isJsonObject()) {
JsonObject jObj = jsonElement.getAsJsonObject();
for(Map.Entry<String, JsonElement> entry : jObj.entrySet()) {
JsonElement value = entry.getValue();
String newPrefix = prefix + entry.getKey();
if(value.isJsonArray() || value.isJsonObject()) {
keys.add(newPrefix);
keys.addAll(operate(value, newPrefix + "_", false));
}
}
} else {
JsonArray array = jsonElement.getAsJsonArray();
for(JsonElement element : array) {
keys.addAll(operate(element, prefix, false));
}
}
return keys;
} else {
return Collections.emptyList();
}
}
and the test method:
public static void test(String json) {
JsonElement jsonElement = new JsonParser().parse(json);
List<String> keys = operate(jsonElement, "", true);
System.out.println("Keys = " + keys);
}
Running it on your example, you'll get:
Keys = [items, items_contact, items_records, items_records_recordings]
How do I access the array products from the below JSON string? I would ideally do this, and it works -
JSONParser parser = new JSONParser();
Object response = parser.parse(json);
JSONObject jsonObject = (JSONObject) response;
JSONObject info = (JSONObject) jsonObject.get("info");
JSONArray data = (JSONArray) jsonObject.get("products");
But the problem is the root element info is not always the same, so I can't hardcode my code. Basically, I don't want to access products by accessing info first. I want to directly access the products array.
How can I do this?
{
"info": {
"products": [
{
"test": 11577,
"number": 2541,
"product": "deoderant",
"id": 1,
"subId": 5,
"tempId": 3,
"name": null,
"lastModified": "2015-05-24",
"lastUsed": 5,
"score": 0.93,
"season": "Seasonal",
"availability": 0,
"itemRanking": null,
"itemQuantity": 5,
"listOfStores": [
7896
]
}
],
"storeId": 10145678
}
}
convert to map, LinkedHashMap or HashMap as per your need, then get the entry value.
public class Test {
public static void main(String[] args) {
String json = "{\"info\": {\"products\": [{\"test\": 11577,\"number\": 2541,\"product\": \"deoderant\",\"id\": 1,\"subId\": 5,\"tempId\": 3,\"name\": null,\"lastModified\": \"2015-05-24\",\"lastUsed\": 5,\"score\": 0.93,\"season\": \"Seasonal\",\"availability\": 0,\"itemRanking\": null,\"itemQuantity\": 5,\"listOfStores\": [7896]}],\"storeId\": 10145678}}";
JSONObject jsonObject;
try {
jsonObject = new JSONObject(json);
Map<String, Object> map = getMap(jsonObject);
for (Map.Entry<String, Object> entry : map.entrySet()) {
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static Map getMap(JSONObject object) {
Map<String, Object> map = new LinkedHashMap<String, Object>();
Object jsonObject = null;
String key = null;
Object value = null;
try {
Iterator<String> keys = object.keys();
while (keys.hasNext()) {
key = null;
value = null;
key = keys.next();
if (null != key && !object.isNull(key)) {
value = object.get(key);
}
if (value instanceof JSONObject) {
map.put(key, getMap((JSONObject) value));
continue;
}
if (value instanceof JSONArray) {
JSONArray array = ((JSONArray) value);
List list = new ArrayList();
for (int i = 0 ; i < array.length() ; i++) {
jsonObject = array.get(i);
if (jsonObject instanceof JSONObject) {
list.add(getMap((JSONObject) jsonObject));
} else {
list.add(jsonObject);
}
}
map.put(key, list);
continue;
}
map.put(key, value);
}
} catch (Exception e) {
System.out.println(e);
}
return map;
}
}
Output
info
{products=[{test=11577, number=2541, product=deoderant, id=1, subId=5, tempId=3, name=null, lastModified=2015-05-24, lastUsed=5, score=0.93, season=Seasonal, availability=0, itemRanking=null, itemQuantity=5, listOfStores=[7896]}], storeId=10145678}
I don't know if this is the best way - but you can always get the keys of your objects with the keys() method. So you will know the name of the top object.
Use fasterxml lib,you can write code like below:
ObjectMapper mapper = new ObjectMapper();
// json is your json string
String json = "";
JsonNode jsonNode = node.findParent("products").get("products");
System.out.println(jsonNode);
I want to find the size of each value from the key-value pair in Map<Integer, ArrayList<String>>. Simply writing list.size() does not work.
Here's my code:
public void getF() throws Exception {
BufferedReader br2 =
new BufferedReader(
new FileReader("/home/abc/NetBeansProjects/network1.txt"));
System.out.println("hello" +r.usr);
while ((s= br2.readLine()) != null) {
String F[]= s.split(":");
for (String uid : F) {
if (uid == F[0]) {
user.add(uid);
} else {
li = followee.get(Integer.valueOf(F[0]));
if (li == null) {
followee.put(Integer.valueOf(F[0]), li= new ArrayList<String>());
}
li.add(uid);
}
System.out.println(followee);
int g = li.size();
System.out.println("g:" +g);
[...]
}
}
}
Why am I not getting correct size on last line?
Try to follow the data structures, by keeping the variable as close to their usage.
(I know in other languages the convention is to declare them at the top.)
Here li should be kept at the begin of a while-step. And its more natural to handle f[0] outside the loop, instead of for+if. I think the latter put you on the wrong foot.
Set<String> user = new HashSet<>();
Map<Integer, List<String>> followee = new HashMap<>();
String s;
while ((s = br2.readLine()) != null) {
// s has the format "key:value value value"
String keyAndValues[] = s.split(":", 2);
if (keyAndValues.length != 2) {
continue;
}
Integer key = Integer.valueOf(keyAndValues[0]);
String values = keyAndValues[1];
user.add(keyAndValues[0]);
List<String> li = followee.get(key);
if (li == null) {
li = new ArrayList<>();
followee.put(key, li);
}
Collections.addAll(values.split(" +");
System.out.println(followee);
int g = li.size();
System.out.println("g:" + g);
//[...]
}
Lets say I gave a JSONObject
{
"person":{"name":"Sam", "surname":"ngonma"},
"car":{"make":"toyota", "model":"yaris"}
}
How do I update some of the values in the JSONObject?
Like below :
String name = jsonArray.getJSONObject(0).getJSONObject("person").getString("name");
name = "Sammie";
Use the put method: https://developer.android.com/reference/org/json/JSONObject.html
JSONObject person = jsonArray.getJSONObject(0).getJSONObject("person");
person.put("name", "Sammie");
Remove key and then add again the modified key, value pair as shown below :
JSONObject js = new JSONObject();
js.put("name", "rai");
js.remove("name");
js.put("name", "abc");
I haven't used your example; but conceptually its same.
Hello I can suggest you universal method. use recursion.
public static JSONObject function(JSONObject obj, String keyMain,String valueMain, String newValue) throws Exception {
// We need to know keys of Jsonobject
JSONObject json = new JSONObject()
Iterator iterator = obj.keys();
String key = null;
while (iterator.hasNext()) {
key = (String) iterator.next();
// if object is just string we change value in key
if ((obj.optJSONArray(key)==null) && (obj.optJSONObject(key)==null)) {
if ((key.equals(keyMain)) && (obj.get(key).toString().equals(valueMain))) {
// put new value
obj.put(key, newValue);
return obj;
}
}
// if it's jsonobject
if (obj.optJSONObject(key) != null) {
function(obj.getJSONObject(key), keyMain, valueMain, newValue);
}
// if it's jsonarray
if (obj.optJSONArray(key) != null) {
JSONArray jArray = obj.getJSONArray(key);
for (int i=0;i<jArray.length();i++) {
function(jArray.getJSONObject(i), keyMain, valueMain, newValue);
}
}
}
return obj;
}
It should work. If you have questions, go ahead.. I'm ready.
Generic way to update the any JSONObjet with new values.
private static void updateJsonValues(JsonObject jsonObj) {
for (Map.Entry<String, JsonElement> entry : jsonObj.entrySet()) {
JsonElement element = entry.getValue();
if (element.isJsonArray()) {
parseJsonArray(element.getAsJsonArray());
} else if (element.isJsonObject()) {
updateJsonValues(element.getAsJsonObject());
} else if (element.isJsonPrimitive()) {
jsonObj.addProperty(entry.getKey(), "<provide new value>");
}
}
}
private static void parseJsonArray(JsonArray asJsonArray) {
for (int index = 0; index < asJsonArray.size(); index++) {
JsonElement element = asJsonArray.get(index);
if (element.isJsonArray()) {
parseJsonArray(element.getAsJsonArray());
} else if (element.isJsonObject()) {
updateJsonValues(element.getAsJsonObject());
}
}
}
public static JSONObject updateJson(JSONObject obj, String keyString, String newValue) throws Exception {
JSONObject json = new JSONObject();
// get the keys of json object
Iterator iterator = obj.keys();
String key = null;
while (iterator.hasNext()) {
key = (String) iterator.next();
// if the key is a string, then update the value
if ((obj.optJSONArray(key) == null) && (obj.optJSONObject(key) == null)) {
if ((key.equals(keyString))) {
// put new value
obj.put(key, newValue);
return obj;
}
}
// if it's jsonobject
if (obj.optJSONObject(key) != null) {
updateJson(obj.getJSONObject(key), keyString, newValue);
}
// if it's jsonarray
if (obj.optJSONArray(key) != null) {
JSONArray jArray = obj.getJSONArray(key);
for (int i = 0; i < jArray.length(); i++) {
updateJson(jArray.getJSONObject(i), keyString, newValue);
}
}
}
return obj;
}
Recursive way to update value in depth in Kotlin
Example: setJsonValue("obj1/obj2/keyToUpdate", "new value")
fun setJsonValue(path: String, value: Any?) {
setJsonValueRec(
path = path.split("/"),
index = 0,
obj = jsonObj,
value = value
)
}
private fun setJsonValueRec(path: List<String>, index: Int, obj: JSONObject, value: Any?): JSONObject {
return obj.put(
path[index],
when (index) {
path.lastIndex -> value
else -> setJsonValueRec(
path = path,
index = index + 1,
obj = obj.getJSONObject(path[index]),
value = value
)
}
)
}