I have a csv file with an initial data for my app.
{
"id": 1,
"topic": "Архитектура",
"question": "Как называется буддийское архитектурное культовое сооружение?",
"rightanswer": "Ступа",
"wronganswer1": "Баба",
"wronganswer2": "Яга",
"wronganswer3": "Метла",
"passed": false,
"right": false
},
I need to parse it to json with the array of "answers", what options i have ?
Result should be like that :
{
"id": 1,
"topic": "Архитектура",
"question": "Как называется буддийское архитектурное культовое сооружение?",
"answers":[
"Ступа",
"Баба",
"Яга",
"Метла" ],
"passed": false,
"right": false
}
You are almost in the right direction but you have to use JSONArray for answers rather then adding them directly into the object with the name.
you can have an if where you will check if key contains the answer string then you can add into the JSONArray else add that key and value into JSONObject and add this JSONArray with the key answers into the main object once you done by adding all field.
This logic will keep your logic flexible.
it will help you to achieve your desire JSON.
EDIT: I would suggest you change your excel structure if you can. you should have all possible options in a single column (such as opt1,opt2,opt3,opt4) and correct answers in another column to gain simplicity and flexibility in your excel designa nd code.
I'm using gson
String str = "{\r\n" +
" \"id\": 1,\r\n" +
" \"topic\": \"Архитектура\",\r\n" +
" \"question\": \"Как называется буддийское архитектурное культовое сооружение?\",\r\n" +
" \"rightanswer\": \"Ступа\",\r\n" +
" \"wronganswer1\": \"Баба\",\r\n" +
" \"wronganswer2\": \"Яга\",\r\n" +
" \"wronganswer3\": \"Метла\",\r\n" +
" \"passed\": false,\r\n" +
" \"right\": false\r\n" +
" }"; //<== your json input
JsonParser parser = new JsonParser();
JsonObject input = parser.parse(str).getAsJsonObject(); //parser you Json to object
JsonObject output = new JsonObject();//my new jsonOutput
output.add("id", input.get("id"));
//other field .....
//the trick start here
JsonArray answer = new JsonArray();
answer.add(input.get("rightanswer"));
answer.add(input.get("wronganswer1"));
answer.add(input.get("wronganswer2"));
answer.add(input.get("wronganswer3"));
output.add("answers", answer);
System.out.println(output.toString());
result
{"id":1,"answers":["Ступа","Баба","Яга","Метла"]} // to lazy to parse other field sorry
Hope it helps
Related
I have a following JSON
"CustomError": {
"ErrorDesc": "Method Not Allowed",
"Error": "RaiseFault",
"ErrorCode": "405"
}
When I am converting it to JSONObject the order of the K-V are getting changed.
This is my piece of code
JSONObject policies = new JSONObject("\"CustomError\": {\n" +
" \"ErrorDesc\": \"Method Not Allowed\",\n" +
" \"Error\": \"RaiseFault\",\n" +
" \"ErrorCode\": \"405\"\n" +
" }");
policies.get("CustomError");
The returns the random order of K-V.
I know the org.JSON internally uses HashMap and not LinkedHashMap. But is there any way I can attain the order of K-V of my CustomError.
I been trying to solve this issue for quite a while now but i don't seem to have anymore route to take.
I had some backslash that i managed to remove with replace("\", "") but i still have some Quotation Mark like this one ---> " just in the beginning of my map and I don't have any idea how it gets there.
Here is my code:
public void actionPerformed(ActionEvent e) {
JsonObject obj = new JsonObject();
JsonArray ingredList = new JsonArray();
Map<String, String> ingredientAsMap = new HashMap<>();
JsonArray prepTime = new JsonArray();
Map<String, String> prepTimeAsMap = new HashMap<>();
JsonArray cookTime = new JsonArray();
Map<String, String> cookTimeAsMap = new HashMap<>();
obj.addProperty("Recipe Name", textField1.getText().toString());
for (int r = 0; r < model.getRowCount(); r++) {
ingredientAsMap.put("Ingredient", model.getValueAt(r, 0).toString());
ingredientAsMap.put("Measure", model.getValueAt(r, 1).toString());
ingredientAsMap.put("Quantity", model.getValueAt(r, 2).toString());
ingredList.add(String.valueOf(ingredientAsMap));
}
obj.addProperty("Ingredients Lists", String.valueOf(ingredList));
obj.addProperty("Preparation", editorPane1.getText().toString());
prepTimeAsMap.put("Hours", spinner3.getValue().toString());
prepTimeAsMap.put("Mins", spinner2.getValue().toString());
prepTime.add(String.valueOf(prepTimeAsMap));
obj.addProperty("Preparation Time", String.valueOf(prepTime));
cookTimeAsMap.put("Hours", spinner1.getValue().toString());
cookTimeAsMap.put("Mins", spinner4.getValue().toString());
cookTime.add(String.valueOf(cookTimeAsMap));
obj.addProperty("Cooking Time", String.valueOf(cookTime));
Gson gson = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
String json = gson.toJson(obj).replace("\\", "");
try{
FileWriter writer = new FileWriter(System.getProperty("user.dir") + "\\" + textField1.getText().toString() + ".json");
BufferedWriter bw = new BufferedWriter(writer);
bw.write(json);
bw.close();
} catch (IOException e1) {
e1.printStackTrace();
}
System.out.println(json);
//System.out.println(System.getProperty("user.dir") + "\\" + textField1.getText().toString() + ".json");
}
Here is the output I get when my form is filled:
{
"Recipe Name": "Test",
"Ingredients Lists": "["{Ingredient=Ingredient0, Measure=ml, Quantity=0}","{Ingredient=Ingredient1, Measure=ml, Quantity=0}"]",
"Preparation": "This is a test.",
"Preparation Time": "["{Hours=0, Mins=0}"]",
"Cooking Time": "["{Hours=0, Mins=0}"]"
}
Notice the " before the [ in Ingredient List, Preparation Time and Cooking Time. How do I get rid of them?
Thanks in advance!
Your issue starts with lines like these
obj.addProperty("Ingredients Lists", String.valueOf(ingredList));
obj.addProperty("Preparation Time", String.valueOf(prepTime));
For the HashMaps, refer How to convert hashmap to JSON object in Java (not the accepted one, but the Gson answer)
Similarly, for the JSONArray, you don't need to String.value them. Just add directly. From the API, use the add(String name, JsonElement element) method.
obj.add("Preparation Time", prepTime);
Detailed answer
Stop string replacing. Your internal data sets are just not JSON, so you are building that JSON incorrectly.
Notice the syntax highlighting
Invalid
{ "Preparation Time": "["{Hours=0, Mins=0}"]" }
Valid - The inner string is escaped.
{ "Preparation Time": "[\"{Hours=0, Mins=0}\"]" }
Which is essentially seen as this to any JSON parser
{ "Preparation Time": "..." }
You can getString("Preparation Time"), and it returns "[\"{Hours=0, Mins=0}\"]" as a String. If you convert that to a JSONArray, then it's an array of strings. Print the first element, you should only see "{Hours=0, Mins=0}" (quotes are kept), and so you should be replacing the quotes and {} characters, not the backslashes. And you could split on equal signs to get key-values, and etc,etc... but that sounds like a lot of work.
Basically, there are no equal signs in key-value JSON pairs.
{Ingredient=Ingredient0, Measure=ml, Quantity=0}
So, Gson is doing to treat every single one of those keys's values as String type and any quotes or backslashes are going to be unescaped when you print the data, but it is stored in memory escaped.
However you want to parse the extra data is unrelated to JSON parsing, so that is my hint and you can stop scratching your head hopefully.
For what it's worth, here is JSON for that data. So, my suggestion is to fix the model class and pieces of code that generate this data.
{
"Recipe Name": "Test",
"Ingredients Lists": [{
"Ingredient": "Ingredient0",
"Measure": "ml",
"Quantity": 0
}, {
"Ingredient": "Ingredient1",
"Measure": "ml",
"Quantity": 0
}],
"Preparation": "This is a test.",
"Preparation Time": [{
"Hours": 0,
"Mins": 0
}],
"Cooking Time": [{
"Hours": 0,
"Mins": 0
}]
}
I'm trying to create a JSON object that looks like:
{
"values": {
"barcode": "{"title":"611269991000grant"}"
}
}
Note that the value of barcode is only a string. Here's what I'm writing:
// title = 611269991000grant
params = new JSONObject("{\"values\": {\"barcode\":" + "\"{\"title\":\"" + title + "\"}\" } }");
The problem however is that this will throw an exception saying
Unterminated object at character 26 of {"values": {"barcode":"{"title":"611269991000grant"}" } }
Anyone know what i'm doing wrong?
That's invalid JSON. Change
params = new JSONObject("{\"values\": {\"barcode\":" + "\"{\"title\":\"" + title + "\"}\" } }");
to
params = new JSONObject("{\"values\": {\"barcode\":" + "{\"title\":\"" + title + "\"} } }");
So that your JSON would finally be:
{
"values": {
"barcode": {"title":"611269991000grant"}
}
}
If your intent is that the value of barcode is a String representation of a document, and not a document ,then
"{"title":"611269991000grant"}"
is not valid, you either scape the inner double quotes " with \ or you replace the inner double quotes " with single quotes '
{
"values": {
"barcode": "{'title':'611269991000grant'}"
}
}
or
{
"values": {
"barcode": "{\"title\":\"611269991000grant\"}"
}
}
Found a solution to my problem:
String jsonobj = "{\\\"title\\\":\\\"" + title + "\\\"}";
params = new JSONObject("{\"values\": {\"barcode\":\"" + jsonobj + "\"} }");
I needed to double escape because the value of barcode is sent over a stream and I still needed it to be in JSON format. So my program now reads the JSON object as
{"values":{"barcode":"{\"title\":\"611269991000,grant\"}"}}
and the barcode value is sent to the stream and read by the webapp as
{"title":"611269991000,grant"}
pseudo JSON! I forgot to mention that the barcode value can only contain a string, which is why I was trying to do magic.
Before this is marked as a duplicate please read the question (I did look at similar ones). Thank you.
For simplicity, assume I have JSON like this:
{
"clients" : [
{
"name" : "client 1",
"id" : 1
},
{
"name" : "client 2",
"id" : 2
}
],
"other" : {
"something" : ""
}
...
}
So I want to create a hash map of only the clients and their fields. The basic question is how would I go about doing this using Jackson methods for a single JSON array like clients? I've tried to look online but all of the examples that I have seen either don't use Jackson or only are for a single JSON object like so:
HashMap<String, String>[] values = new ObjectMapper().readValue(jsonString, new TypeReference<HashMap<String, String>[]>() {});
I've also seen Gson examples and I know I can do some string parsing magic:
jsonSting = jsonString.substring(jsonString.indexOf("["), (jsonString.indexOf("]")+1))
to get it in a format that I can use, but I want to try it with Jackson to avoid importing another library. Any ideas?
Rephrasing the question:
So if I only had a list of clients like so:
jsonString = [{"name" : "client 1","id" : 1},{"name" : "client 2","id" : 2}]
then I could just do:
HashMap[] values = new ObjectMapper().readValue(jsonString, new TypeReference[]>() {});
to get what I want. I am basically asking if there is a way using Jackson methods to get the jsonString above from the large JSON section on top. I know I can easily do it with this example with string parsing but there will be more complex situations in the future and string parsing is not really considered best practice
You can extract a part of the JSON tree using the Jackson tree model API and then convert it to an array of maps.
Here is an example:
public class JacksonReadPart {
public static final String JSON = "{\n" +
" \"clients\" : [\n" +
" {\n" +
" \"name\" : \"client 1\",\n" +
" \"id\" : 1\n" +
" },\n" +
" {\n" +
" \"name\" : \"client 2\",\n" +
" \"id\" : 2\n" +
" }\n" +
"],\n" +
" \"other\" : {\n" +
" \"something\" : \"\"\n" +
" }\n" +
"\n" +
"}";
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
JsonNode node = mapper.readTree(JSON).path("clients");
// non type safe
Map<String, Object>[] clients = mapper.treeToValue(node, Map[].class);
System.out.println(Arrays.toString(clients));
// type safe
JsonParser parser = mapper.treeAsTokens(node);
clients = parser.readValueAs(new TypeReference<Map<String, Object>[]>() {});
System.out.println(Arrays.toString(clients));
}
}
Output:
[{name=client 1, id=1}, {name=client 2, id=2}]
[{name=client 1, id=1}, {name=client 2, id=2}]
I am trying to parse json to java.
I have the following string that is valid json according to jsonlint.com
private final static String LOC_JSON =
"["
+"{"
+" \"lat1\": 39.737567,"
+" \"lat2\": 32.7801399,"
+" \"long1\": -104.98471790000002,"
+" \"long2\": -96.80045109999998"
+"},"
+" ["
+" {"
+" \"lat\": {"
+" \"b\": 38.88368709500021,"
+" \"d\": 40.620468491667026"
+" },"
+" \"long\": {"
+" \"b\": -105.75306170749764,"
+" \"d\": -104.675854661387"
+" }"
+" }"
+" ]"
+"]";
I am trying to parse it into an object and I get the following error.
"Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2"
Gson gson = new Gson();
BoxSearch b = gson.fromJson( LOC_JSON, BoxSearch.class );
BoxSearch consists of this.
private Number lat1;
private Number lat2;
private Number long1;
private Number long2;
private Boxes[] boxes;
Boxes is a Latitude object and a Longitude object which are both defined identical.
private String b;
private String d;
I can parse the higher level attributes (lat1,lat2,long1 and long2) into a more simple BoxSearch object that only has those 4 attributes. The trouble comes when the json and the object are more complex. Is it even possible to do what I am trying?
I hope I have provided enough information to get some help. I would be happy to provide more info or even a test project if need be. I am running this as a junit test.
Thanks.
Gson gson = new Gson();
gson.fromJson(jsonStr,YourClass.class);
very easy.
The reason for the error is that your JSON at the top level is an array, not an object. That is covered by GSON throwing "Expected BEGIN_OBJECT but was BEGIN_ARRAY"?.
However, the solution there won't work for your JSON because you have an array of mixed types (an object and an array) rather than an array of a single type of object. For that you're going to have to write a custom deserializer (See The section of the Gson user's guide that covers this) or use Gson's JsonParser class directly and extract the data from the parse tree.
Edit from comments above:
If you're the one creating the JSON, it looks like what you want is an array of BoxSearch objects?
Based on your Java BoxSearch class, you'd need JSON structured like:
[
{
"lat1" : 39.737567,
"lat2" : 32.7801399,
"long1" : -104.98471790000002,
"long2" : -96.80045109999998,
"boxes" : [
{
"lat": {
"b": 38.88368709500021,
"d": 40.620468491667026
},
"long": {
"b": -105.75306170749764,
"d": -104.675854661387
}
}
]
}
]
However, the way you have Boxes class defined won't work for that. (Did you mean to have an array of them?). As-is it would need to look like:
class Boxes {
Box lat;
#SerializedName("long")
Box lon;
}
class Box {
String b;
String d;
}
Now you have an array containing one type of object (BoxSearch) which you could deserialize with:
Type collectionType = new TypeToken<Collection<BoxSearch>>(){}.getType();
Collection<BoxSearch> boxSearchCollection = gson.fromJson(json, collectionType);
If you really don't need an array of these, get rid of the outer array and simply do:
gson.fromJson(json, BoxSearch.class);