How to query JSON with wildcards and modify the results? - java

I'd like to be able to query a JSON object and modify it in a way that is structure-agnostic and doesn't involve marshalling to POJOs. Here's an example to illustrate.
{
"user" : [ {
"username" : "foo",
"user-id" : "1234",
"name" : {
"first-name" : "John",
"last-name" : "Smith"
},
"ssn": "123-45-6789"
}, {
"username" : "bar",
"user-id" : "1235",
"name" : {
"first-name" : "Jane",
"last-name" : "Doe"
},
"ssn": "098-76-5432"
} ]
}
What I want to do is this:
Get the ssn nodes, retrieve their values, encrypt them, put the encrypted values back in the JSON, and return the whole thing. I've found two ways to do this so far:
Marshalling to a User POJO
Writing a method that iterates over the "user"s directly and modifies the ssn value.
The problem with either approach is that I have to generate "user" specific code. This is fine when I have only one data format, but I'm going to have dozens. I want to work more agnostically. Ideally I can do this with a line like this:
List<JsonNode> ssnNodes = jsonObj.match("$.user[*].ssn");
and then just iterate over the list -- just as I can with XML using XPath. This way I can maintain a list of json-paths to query with and that is as much as I need to know about the data.
Someone please tell me there is a way to do this in Java, but I haven't found a way so far. Thanks in advance!

Related

Json to csv conversion in Spring boot

I have a csv structure like this
and I also have one json response
[
{
"ID" : "1",
"Name" : "abc",
"Mobile" : "123456"
},
{
"ID" : "2",
"Name" : "cde",
"Mobile" : "123345"
}
]
I need the output like this
If your intention is to convert directly the JSON then that baeldung solution that you were given is good.
Otherwise, the way i see it and based on the info you're giving, you will need to have a representation of that JSON in a java object that will either represent some kind of request coming from somewhere or data you're getting from your database in order to be written on a csv.
Check out these, might be useful:
https://www.codejava.net/frameworks/spring-boot/csv-export-example
https://zetcode.com/springboot/csv/

mongodb java driver pullByFilter

I have document schema such as
{
"_id" : 18,
"name" : "Verdell Sowinski",
"scores" : [
{
"type" : "exam",
"score" : 62.12870233109035
},
{
"type" : "quiz",
"score" : 84.74586220889356
},
{
"type" : "homework",
"score" : 81.58947824932574
},
{
"type" : "homework",
"score" : 69.09840625499065
}
]
}
I have a solution using pull that copes with removing a single element at a time but saw
I want to get a general solution that would cope with irregular schema where there would be between one and many elements to the array and I would like to remove all elements based on a condition.
I'm using mongodb driver 3.2.2 and saw this pullByFilter which sounded good
Creates an update that removes from an array all elements that match the given filter.
I tried this
Bson filter = and(eq("type", "homework"), lt("score", highest));
Bson u = Updates.pullByFilter(filter);
UpdateResult ur = collection.updateOne(studentDoc, u);
Unsurprisingly, this did not have any effect since I wasn't specifying the array scores
I get an error
The positional operator did not find the match needed from the query. Unexpanded update: scores.$.type
when I change the filter to be
Bson filter = and(eq("scores.$.type", "homework"), lt("scores.$.score", highest));
Is there a one step solution to this problem?
There seems very little info on this particular method I can find. This question may relate to How to Update Multiple Array Elements in mongodb
After some more "thinking" (and a little trial and error), I found the correct Filters method to wrap my basic filter. I think I was focusing on array operators too much.
I'll not post it here in case of flaming.
Clue: think "matches..." (as in regex pattern matching) when dealing with Filters helper methods ;)

How to make a JsonObject in a ordered way?

I want to create a JSonObject with some values for call a webservice but where webservice in a order like:
{
"id" : 1
"email" : "test#test.com",
"pin" : 1234,
"age" : 25,
"firstName" : "Test First Name",
"lastName" : "Test Last Name",
"location" : "India",
"phone" : "1234567890"
}
but when I create a json object from android code it is not maintaining the order like:
requestJOB=new JSONObject();
requestJOB.put("userid",Pref.getValue(this, Const.USER_ID, requestJOB.optString("userid")));
requestJOB.put("email", Pref.getValue(this, Const.PREF_EMAIL, requestJOB.optString("email")));
requestJOB.put("pin", Pref.getValue(this, Const.PREF_PIN, requestJOB.optString("pin")));
requestJOB.put("age", Pref.getValue(this, Const.PREF_AGE, requestJOB.optString("age")));
requestJOB.put("firstname", etFirstName.getText().toString().trim());
requestJOB.put("lastname", etLastName.getText().toString().trim());
requestJOB.put("phone", etPhone.getText().toString().trim());
requestJOB.put("location", etLocation.getText().toString().trim());
I write the code my desired order but JsonObject change the order in run time. I also tried with map and LinkedList but A exception is
occured when I want to convert LIST to JsonObject.
I searched in stackoverflow where no satisfactory answer.
In this situation I don't understand exactly what I have to do.
In Android platform there is better way to serialize a object in json by using Google GSON API... Which provide all possible functionality to convert a class to their corresponding JSON. U can prepare nested jsonobject ..
Nested like json object with in a json object. Json array embedded within a json. Object
Multiple jsonarray with in a same json object. And their may be multiple variety .. Just explore this jar .. It's very easy to use and user-friendly jar. Just go and grab it .. Hopefully u feel better with this API
I used this jar in my Android project actually

mongoDB: $inc of a nonexistent document in an array

I was not able to write a code, which would be able to increment a non-existent value in an array.
Let's consider a following structure in a mongo collection. (This is not the actual structure we use, but it maintains the issue)
{
"_id" : ObjectId("527400e43ca8e0f79c2ce52c"),
"content" : "Blotted Science",
"tags_with_ratings" : [
{
"ratings" : {
"0" : 6154,
"1" : 4974
},
"tag_name" : "math_core"
},
{
"ratings" : {
"0" : 154,
"1" : 474,
},
"tag_name" : "progressive_metal"
}
]
}
Example issue: We want to add to this document into the tags_with_ratings attribute an incrementation of a rating of a tag, which is not yet added in the array. For example we would want to increment a "0" value for a tag_name "dubstep".
So the expected behaviour would be, that mongo would upsert a document like this into the "tags_with_ratings" attribute:
{
"ratings" : {
"0" : 1
},
"tag_name" : "dubstep"
}
At the moment, we need to have one read operation, which checks if the nested document for the tag is there. If it's not, we pull the array tags_with_ratings out, create a new one, re-add the values from the previous one and add the new nested document in there. Shouldn't we be able to do this with one upsert operation, without having the expensive read happen?
The incrementation of the values takes up 90% of the process and more than half of it is consumed by reading, because we are unable to use $inc capability of creating an attribute, if it is non-existent in the array.
You cannot achieve what you want with one step using this schema.
You could do it however if you used tag_name as the key name instead of using ratings there, but then you may have a different issue when querying.
If the tag_name value was the field name (replacing ratings) you'd have {"dubstep":{"0":1}} instead of { "ratings" : {"0" : 1},"tag_name" : "dubstep"} which you can update dynamically the way you want to. Just keep in mind that this schema will make it more difficult to query - you have to know what the ratings are in advance to be able to query by keyname.

Do JSON keys need to be unique? [duplicate]

This question already has answers here:
Does JSON syntax allow duplicate keys in an object?
(12 answers)
Closed 6 years ago.
The following question is related to a question that I had asked earlier: Help parsing simple JSON (using JSON for JAVA ME)
Do JSON keys need to be unique? For example, I was having trouble parsing the following XML (with JSON ME):
{
"name" : "JACK",
"name" : "JILL",
"name" : "JOHN",
"name" : "JENNY",
"name" : "JAMES",
"name" : "JIM"
}
And, apparently, its because the keys must be unique. I'm just wondering if thats true in all cases or not. For example, if I were using something other than JSON ME, would I be able to parse all of these names?
Thanks.
There is no "error" if you use more than one key with the same name, but in JSON, the last key with the same name is the one that is going to be used.
In your case, the key "name" would be better to contain an array as it's value, instead of having a number of keys "name". It doesn't make much sense the same object or "thing" to have two names, or two of the same properties that are in conflict.
E.g.:
{
"name" : [ "JOHN", "JACK", "...", ... ]
}
From RFC 4627:
An object structure is represented as a pair of curly brackets
surrounding zero or more name/value pairs (or members). A name is a
string. A single colon comes after each name, separating the name
from the value. A single comma separates a value from a following
name. The names within an object SHOULD be unique.
jQuery is able to parse it. But if you try to access it, it's just giving back the last value.
Check out
http://jsfiddle.net/MQmM4/2/
So, it's parsable, I guess, but the value gets overridden if you use the same key.
here is a possible solution using array. just use array index
the_json_array.getJSONObject(0);
{"nameList":
[{"name" : "JACK"},
{"name" : "JILL"},
{"name" : "JOHN"},
{"name" : "JENNY"},
{"name" : "JAMES"},
{"name" : "JIM"}]}
A JSON Object looks like the following
public JSONObject(Map<?, ?> map) {
this.map = new HashMap<String, Object>();
if (map != null) {
for (final Entry<?, ?> e : map.entrySet()) {
final Object value = e.getValue();
if (value != null) {
this.map.put(String.valueOf(e.getKey()), wrap(value));
}
}
}
}
A JSON Object is basically a hashmap containing key value pair.
This is why you are getting overwritten each time. To avoid this
Either you must have unique key values
Or you should wrap the key value pair as individual objects into an array
Have a look at this JSON Object java implementation to know in depth about JSON.

Categories