How to convert array of objects to Spring application.properties - java

I'm using Jackson to convert objects include Array object to application.properties file but the result when convert array object look not good as I expected.
This is my code:
JSONSerializer serializer = new JSONSerializer().rootName("application").prettyPrint(false);
String json = serializer.serialize(configDto.getValue());
ObjectMapper om = new ObjectMapper();
JsonNode tree = om.readTree(json);
Properties props;
JavaPropsMapper mapper = new JavaPropsMapper();
props = mapper.writeValueAsProperties(tree);
props.store(new FileOutputStream(file), "");
Input:
{
"nation": [
{
"key": "France"
},
{
"key": "Spain"
},
{
"key": "England"
}
],
"movie": "Avatar 2"
}
Result:
application.nation.1 = France
application.nation.2 = Spain
application.nation.3 = England
application.movie = Avatar 2
Result expect:
application.nation[1] = France
application.nation[2] = Spain
application.nation[3] = England
application.movie = Avatar 2
How I can convert data like result I expect? Sorry for my bad English! Thanks!

Possibly make your nation in your json an array. I'm sorry, I haven't tested it.
{
"nation": ["France", "Spain", "England"],
"movie": "Avatar 2"
}

Related

Cannot make json valid for recyclerview

I'm trying to JSON using Gson and recyclerview. My JSON isnt completely valid. In my JSON, the food field has only one of the string quoted leaving the other unquoted. Kindly see my JSON below...
[
{"quantity" = 2,
"price" = 15,
"food" = "Fried" Rice},
{"quantity" = 2,
"price" = 20,
"food" = "Rice" and Stew}
]
You can see that Fried is in quotes and Rice isnt in quotes, likewise the same for Rice and Stew in the other too. Initially it was like this ...
[
{quantity = 2,
price = 15,
food = Fried Rice},
{quantity = 2,
price = 20,
food = Rice and Stew}
]
My activity class code...
Bundle extras = getIntent().getExtras();
if (extras != null) {
String listOfFood = extras.getString("foods");
listOfFood = listOfFood.replaceAll("([\\w]+)[ ]*=", "\"$1\" ="); // to quote before = value
listOfFood = listOfFood.replaceAll("=[ ]*([\\w#\\.]+)", "= \"$1\""); // to quote after = value, add special character as needed to the exclusion list in regex
listOfFood = listOfFood.replaceAll("=[ ]*\"([\\d]+)\"", "= $1"); // to un-quote decimal value
listOfFood = listOfFood.replaceAll("\"true\"", "true"); // to un-quote boolean
listOfFood = listOfFood.replaceAll("\"false\"", "false"); // to un-quote boolean
Log.d(TAG, "onCreate: "+listOfFood);
GsonBuilder builder = new GsonBuilder();
Gson mGson = builder.create();
List<FoodOrder> posts = new ArrayList<FoodOrder>();
posts = Arrays.asList(mGson.fromJson(listOfFood, FoodOrder[].class));
adapter = new RecyclerViewAdapter(FoodsOrderedActivity.this, posts);
recyclerView.setAdapter(adapter);
}
I need the food field that has Fried Rice to be inbetween quotes as one and the same for rice and stew or if theres a workaround, I would like to know.
Thank you
Base on your code. (Try to convert listOfFood to JSON )
I modify 2 lines of your code as bellow
listOfFood = listOfFood.replaceAll("(\\s*)([^{,\\s]+)(\\s*)=","$1\"$2\"$3:"); // to quote before = value and replace = by :
listOfFood = listOfFood.replaceAll("(:\\s*)([^\\s,{}](\\s*[^\\s,{}]+)*)", "$1\"$2\""); // to quote after = value (= now became :)
The json structure should look like as below
[
{
"Key1" : "value1",
"Key2" : "value2",
},
{
"Key1" : "value1",
"Key2" : "value2",
}
]
The json structure should be like this :
[{"quantity" : 2,
"price" : 15,
"food" : "Fried Rice"},
{"quantity" : 2,
"price" : 20,
"food" : "Rice and Stew"}]

Java : JSONObject.put looped gives wrong order?

Today I started writing a simple parser for a log file. I want to take the log file and transform it into a simple json structure.
The log file is consistent and has 3 main parts (example below):
the timestamp [23 digits]
the code [4 digits]
the payload [variable digits]
Example log
2018-07-25T08:47:16,094,164f,test1
2018-07-25T08:47:18,163,1678,test2
2018-07-25T08:47:19,501,1662,test3
2018-07-25T08:47:21,278,1634,test4
2018-07-25T08:47:23,347,1632,test5
2018-07-25T08:47:24,686,1665,test6
2018-07-25T08:47:26,463,1678,test7
2018-07-25T08:47:28,533,1678,test8
2018-07-25T08:47:29,877,1632,test9
2018-07-25T08:47:31,687,1632,test10
From this I wanted to create a JSON file that would incorporate well the information inside. This is what I came up with (using org.json.JSONObject library).
BufferedReader reader = new BufferedReader(new FileReader ("file.log"));
String line = null;
String timestamp = null;
String eventCode = null;
String payload = null;
JSONObject codePayload = new JSONObject();
JSONObject finalString = new JSONObject();
for (int i = 0; i < 10; i++) {
line = reader.readLine();
timestamp = line.substring(0, 23);
eventCode = line.substring(24, 28);
payload = line.substring(29, line.length());
codePayload.put("ID", eventCode);
codePayload.put("PL", payload);
finalString.put(timestamp, codePayload);
codePayload = new JSONObject();
}
System.out.println(finalString.toString());
This little snippet should work quite well (don't mind the for) and it kinda does. It creates the JSON file according to the string I give it but it puts then in a strange order, see below.
{
"2018-07-25T08:47:24,686": {
"ID": "1665",
"PL": "test6"
},
"2018-07-25T08:47:29,877": {
"ID": "1632",
"PL": "test9"
},
"2018-07-25T08:47:31,687": {
"ID": "1632",
"PL": "test10"
},
"2018-07-25T08:47:16,094": {
"ID": "164f",
"PL": "test1"
},
"2018-07-25T08:47:21,278": {
"ID": "1634",
"PL": "test4"
},
"2018-07-25T08:47:18,163": {
"ID": "1678",
"PL": "test2"
},
"2018-07-25T08:47:23,347": {
"ID": "1632",
"PL": "test5"
},
"2018-07-25T08:47:28,533": {
"ID": "1678",
"PL": "test8"
},
"2018-07-25T08:47:19,501": {
"ID": "1662",
"PL": "test3"
},
"2018-07-25T08:47:26,463": {
"ID": "1678",
"PL": "test7"
}
}
As you can clearly see it places the objects in the wrong order and I really don't know why. If someone has the slightest idea on how this problem could occur please comment below. Thanks a lot!
The org.json.JSONObject is un-ordered, so better to use javax.json.JSONObject OR if you are using org.json library, use the org.json.JSONArray to store the timestamps in order.

Dynamic way to access JSON nested values in Java

I have this JSON object:
{
"maindrawer":
{
"enabled": true,
"actions":
[
{
"type": "Section",
"title": "Section 1"
},
{
"id": 1,
"type": "Primary",
"title": "Title 1",
"badge":
{
"enabled": false,
"value": 0,
"textColor": "#000000",
"badgeColor": "#ff0990"
},
"subActions":
[
{
"id": 1,
"type": "Primary",
"title": "Sub Title 1"
}
]
}
]
}
}
This is the code I'm using to access the badge -> textColor value:
public void loadJSONFromRaw(Context context, int id)
{
json = null;
try
{
//read and return json sting
InputStream is = context.getResources().openRawResource(id);
int size = is.available();
byte[] buffer = new byte[size];
is.read(buffer);
is.close();
json = new String(buffer, "UTF-8");
//convert json to object
Type type = new TypeToken<Map<String, Object>>() {}.getType();
Map<String, Object> data = new Gson().fromJson(json, type);
//access maindrawer property
Map<String, Object> maindrawer = (Map<String, Object>)data.get("maindrawer");
//access actions list
List<Object> actions = (List<Object>)maindrawer.get("actions");
//return first item in the list
Map<String, Object> action = (Map<String, Object>) actions.get(1);
//return badge object
Map<String, String> badge = (Map<String, String>) action.get("badge");
//access badge -> textColor value
String textColor = badge.get("textColor");
}
catch (IOException e)
{
e.printStackTrace();
}
}
Is there a better/faster or more dynamic way to access JSON nested properties using java/android? I'm using Gson library for this task and don't mind to switch to any other solution to make it easier as this is too much of code to write just to access a single variable.
Ideally, I'm looking for something like:
String textColor = data.get("maindrawer").get("actions").get(1).get("badge").get("textColor");
Also I'm not very interested in using POJO for now.
Lastly, I'm still new to Java so I'm probably missing something here or maybe there are some limitations? anyways thanks for you help!!
Found what I need using JsonPath library. It looks like it does similar to what I need. Here's a sample code I found:
String textColor = JsonPath.parse(json).read("$.maindrawer.actions[1].badge.textColor");
Very clean and straightforward. Hopes this will save someone else's time as well.
Since you are accessing json file locally, it means you know its structure.
So instead of using -
Map<String, Object> data = new Gson().fromJson(json, type);
You can use something like this-
Map<String, MainDrawer> data = new Gson().fromJson(json, type);
where MainDrawer is a class with member variables - enabled, actions and array of another type.
That would make easier to fetch your values like using -
mainDrawer.isEnabled()
Here are two solutions without importing a new library.
Write a simple path parser:
String textColor = (String)parse(data, "maindrawer", "actions", 1, "badge", "textColor");
//...
static Object parse(Object root, Object... params) {
Object current = root;
for (Object p : params) {
if (p instanceof Number) {
current = ((List<?>)current).get(((Number)p).intValue());
} else {
current = ((Map<?,?>)current).get(p.toString());
}
}
return current;
}
Or parse and walk through Gson's JsonElement:
JsonElement root = new Gson().fromJson(json, JsonElement.class);
String textColor = root
.getAsJsonObject().get("maindrawer")
.getAsJsonObject().get("actions")
.getAsJsonArray().get(1)
.getAsJsonObject().get("badge")
.getAsJsonObject().get("textColor")
.getAsString();
You can also do this with BSON using a single line query. You have to cast the object to the type as you go down into Nested JSON objects.
//import java.util.ArrayList;
//import org.bson.Document;
Document root = Document.parse("{ \"maindrawer\" : { \"enabled\" : true, \"actions\" : [{ \"type\" : \"Section\", \"title\" : \"Section 1\" }, { \"id\" : 1, \"type\" : \"Primary\", \"title\" : \"Title 1\", \"badge\" : { \"enabled\" : false, \"value\" : 0, \"textColor\" : \"#000000\", \"badgeColor\" : \"#ff0990\" }, \"subActions\" : [{ \"id\" : 1, \"type\" : \"Primary\", \"title\" : \"Sub Title 1\" }] }] } }");
System.out.println(((String)((Document)((Document)((ArrayList)((Document)root.get("maindrawer")).get("actions")).get(1)).get("badge")).get("textColor")));

How to get count all json nodes using Jackson framework

Here is my user.json
{
"id":1,
"name":{
"first":"Yong",
"last":"Mook Kim"
},
"contact":[
{
"type":"phone/home",
"ref":"111-111-1234"
},
{
"type":"phone/work",
"ref":"222-222-2222"
}
]
},
{
"id":2,
"name":{
"first":"minu",
"last":"Zi Lap"
},
"contact":[
{
"type":"phone/home",
"ref":"333-333-1234"
},
{
"type":"phone/work",
"ref":"444-444-4444"
}
]
}
I would like count how many json object is in there. For example the above json has 2 json object id = 1 and id =2.
//tree model approach
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(new File("user.json"));
List<JsonNode> listOfNodes = rootNode.findParents("first");
System.out.println(listOfNodes.size());
Giving me size = 1.
Can you please tell me what i am doing wrong?
Thanks
Your java code is correct but your json file is invalid.
Jackson parses only first valid element ("Yong").
To fix this just add [ at the begining and ] at the end of file (make it array).

Parsing json webservice Response with Gson (Expected BEGIN_OBJECT but was BEGIN_ARRAY)

I'm trying to parse the spotify web-service response to get an artists' tracks which is like this:
{
"info": {
"num_results": 2974,
"limit": 100,
"offset": 0,
"query": "foo",
"type": "track",
"page": 1
},
"tracks": [
{
"album": {
"released": "2009",
"href": "spotify:album:1zCNrbPpz5OLSr6mSpPdKm",
"name": "Greatest Hits",
"availability": {
"territories": "AD AR AT AU BE BG BO BR CA CH CL CO CR CY CZ DE DK DO EC EE ES FI FR GB GR GT HK HN HU IE IS IT LI LT LU LV MC MT MX MY NI NL NO NZ PA PE PH PL PT PY RO SE SG SI SK SV TR TW US UY"
}
},
"name": "Everlong",
"popularity": "0.79",
"external-ids": [
{
"type": "isrc",
"id": "USRW29600011"
}
],
"length": 249.986,
"href": "spotify:track:07q6QTQXyPRCf7GbLakRPr",
"artists": [
{
"href": "spotify:artist:7jy3rLJdDQY21OgRLCZ9sD",
"name": "Foo Fighters"
}
],
"track-number": "3"
}]
}
I am using the Gson library to do this. So far I have tried this in my java code:
JsonParser parser = new JsonParser();
JsonObject jObject = parser.parse(jsonString).getAsJsonObject();
JsonArray jArray = jObject.get("tracks") .getAsJsonArray();
Gson gson = new Gson();
List<Track> trackArr = new ArrayList<Track>();
Type collectiontype = new TypeToken<Collection<Track>>(){}.getType();
Collection<Track> trackColl = gson.fromJson(jArray.toString(), collectiontype);
But I am getting the error : com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY
I don't understand why is it expecting begin object if I am doing "getAsJsonArray()" when trying to get the "tracks" object whihc in the json string is an array [].
The list of 'Track' was when I was doing this in a loop to get all the tracks into an array:
for (JsonElement jsonElement : jArray) {
Type collectiontype = new TypeToken<Collection<Track>>(){}.getType();
Collection<Track> trackCol = gson.fromJson(jsonElement, collectiontype);
trackArr.add((Track) trackCol);
}
What am I doind wrong here ?
I appreciate any guidance.
You don`t have to use extra library to parse a JSON file. Also use this link to read your JSON file in a human readable way.
Use the Native one as the following example:
Imports:
import org.json.JSONArray;
import org.json.JSONObject;
The code of parsing will be:
JSONObject fileJSONObject = new JSONObject(response);
JSONObject infoJSONObject = fileJSONObject.getJSONObject("info");
JSONArray tracksJSONArray = fileJSONObject.getJSONArray("tracks");
//Parsing the info
String trackType = infoJSONObject.getString("type");
String trackLimit = infoJSONObject.getString("limit");
//The rest of attributes
//Parsing the track list
JSONObject object;
for(int i=0;i<tracksJSONArray.length();i++){
object = tracksJSONArray.getJSONObject(i);
String trackName = object.getString("name");
//The rest of attributes
}
I recommend for you to Create a track class that contain all the needed attributes and their setter and getter and at the end of the parsing of each track create a new track.
I hope it helps
You can use my lib for solve this problem. For example you can do it.
private static List<Object> SpotifyTest()
{
InformationHandler informationHandler = null;
Injector injector = Guice.createInjector(new Module());
informationHandler = injector.getInstance(SpotifyService.class);
informationHandler.executeWithValue("la bamba");
return informationHandler.getDataModel();
}
The solution returns a List with a lot of HashMap where each key is a enumeration of key on service, the enumarator is:
public enum SpotifyKey
{
ALBUM_RELEASED,
ALBUM_HREF,
ALBUM_NAME,
ALBUM_AVAILABILITY,
NAME,
POPULARITY,
LENGTH,
HREF,
ARTIST_HREF,
ARTIST_NAME,
TRACK_NUMBER,
ID
}
Also you can view the code on github https://github.com/WeCodeMx/WCMPopularService/tree/develop

Categories