I would still need some help with my dynamic selectlist.
I have the sript:
function getMains(element) {
var subjectgroup = element.value;
var select_element;
select_element = '#mains';
$(select_element).html('');
$(select_element).append($("<option></option>").attr("value","none").html(""));
// $(select_element).append($("<option></option>").attr("value","all").html(""));
if (element.value==''||element.value=='none'||element.value=='all')
return;
$.ajax({
type: 'GET',
url: 'getmainsubjects.html',
dataType: 'json',
data: ({id:data}),
success: function(data) {
$.each(function(data) {
if (!subjectgroup) {
$(select_element).append($(" <option>").attr("value",data.id,"items",data).html(data.description));
} else {
$(select_element).append($("<option>").attr("value",data.id,"items",data).html(data.description));
}
});
},
error: function(data) {
//alert("This failed!");
}
});
}
$('select#subjectgroups').ready(function(){
$("select#subjectgroups").find("option").each(function(i) {
if ($(this).val()!='all'&&$(this).val()!='none') {
$(this).append( " " + $(this).val() );
}
});
});
$('select#mains').ready(function(){
$("select#mains").find("option").each(function(i) {
if ($(this).val()!='all'&&$(this).val()!='none') {
$(this).append( " " + $(this).val() );
}
});
});
And the method:
#RequestMapping(method = RequestMethod.GET, params="id", value = "/getmainsubjects")
#ResponseBody
public String getMainSubjects( #RequestParam("id") int id) {
List<MainSubjectsSimple> mains = database.getMainSubjectsSimple(id, Localization.getLanguage());
//System.out.println(mains.size());
HashMap hm = new HashMap();
for (MainSubjectsSimple mss: mains) {
try {
hm.put("id",mss.getId());
hm.put("description", mss.getDescription());
} catch (NoSuchMessageException e) {
//hm.add(Integer.valueOf(mss.getId().toString(), translate(mss.getTranslationCode(),new Locale("fi")));
}
}
String json = null;
String _json = null;
try {
_json = HtmlEntityEncoder.encode(JsonUtils.javaToStr(hm));
} catch (Exception e) {
}
return _json;
}
I think I'm not looping the right values. Mains selectlist should be populated based on other selectlist so that the object's id is the value and description the label. Right now calling the url written in script returns only first object as json, not all of them, and the objects are not shown in mains selectlist.
You are putting the same keys over and over again to the Map hm:
HashMap hm = new HashMap();
for (MainSubjectsSimple mss: mains) {
try {
hm.put("id",mss.getId());
hm.put("description", mss.getDescription());
} catch (NoSuchMessageException e) {
//hm.add(Integer.valueOf(mss.getId().toString(),
translate(mss.getTranslationCode(),new Locale("fi")));
}
}
You need to use different keys for each entry in mains or use a collection (e.g. ArrayList) of Maps. An example of the latter:
List hms = new ArrayList();
for (MainSubjectsSimple mss: mains) {
try {
HashMap hm = new HashMap();
hm.put("id",mss.getId());
hm.put("description", mss.getDescription());
hms.add(hm);
} catch (NoSuchMessageException e) {
//hm.add(Integer.valueOf(mss.getId().toString(), translate(mss.getTranslationCode(),new Locale("fi")));
}
}
...
try {
_json = HtmlEntityEncoder.encode(JsonUtils.javaToStr(hms));
} catch (Exception e) {
}
I'm not familiar with the utils (JsonUtils) you are using so this might not work directly but the principle is the same anyways.
Related
Within my application, I am dynamically creating and returning customers in JSON format. I would like to differentiate each customer, so I am adding a comma after the creation of each customer, but I do not wish to add the comma separation to the last element, so I would like to remove it.
Hence, I need to access the last element and make the modification, but I am running into some problems when doing the same. I tried to do this but was unable to concatenate the same. I am unable to get the last customer without a comma. The following is the code I have:
public static Multi <String> generate(final Input input) {
final ObjectMapper objectMapper = new ObjectMapper();
try {
final Multi < String > generatedCustomer = Multi.createFrom().publisher(CustomerGenerator.createModels(input)).onItem().transform(
event - > {
try {
return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(event) + ",";
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
});
final Multi < String > lastCustomer = generatedEvents.select().last().onItem().transform(i - > i.substring(0, i.length() - 1));
return Multi.createBy().concatenating().streams(generatedCustomer, lastCustomer);
} catch (Exception e) {
throw new CustomerException("Exception occurred during the generation of Customer : " + e);
}
}
How to achieve this?
Updated
My application currently produces customer information in the following format asynchronously, so I would like to add a wrapper to it and make it look like the following JSON.
{
"name": "Batman",
"age": 45,
"city": "gotham"
}
I would like to add a wrapper to it and make it like this:
{
"isA": "customerDocument",
"createdOn": "2022-10-10T12:29:43",
"customerBody": {
"customerList": [
{
"name": "Batman",
"age": 45,
"city": "gotham"
},
{
"name": "superman",
"age": 50,
"city": "moon"
}
]
}
}
Hence, I have added a code something like this:
public static Multi < String > generate(final Input input) {
final ObjectMapper objectMapper = new ObjectMapper();
try {
final Multi < String > beginDocument = Multi.createFrom().items("\"isA\":\"customerDocument\", \"creationDate\":\"" + Instant.now().toString() + "\", \"customerBody\":{ \"customerList\":[");
final Multi < String > generatedCustomer = Multi.createFrom().publisher(CustomerGenerator.createModels(input)).onItem().transform(
event - > {
try {
return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(event) + ",";
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
});
final Multi < String > lastCustomer = generatedEvents.select().last().onItem().transform(i - > i.substring(0, i.length() - 1));
return Multi.createBy().concatenating().streams(beginDocument, generatedCustomer, lastCustomer, Multi.createFrom().items("]}}"));
} catch (Exception e) {
throw new CustomerException("Exception occurred during the generation of Customer : " + e);
}
}
This should do what you've asked:
public static Multi <String> generate(final Input input) {
final ObjectMapper objectMapper = new ObjectMapper();
try {
final Multi<String> generatedCustomer = Multi.createFrom().publisher(CustomerGenerator.createModels(input)).onItem().transform(
event - > {
try {
return objectMapper
.writerWithDefaultPrettyPrinter()
.writeValueAsString(event);
} catch (JsonProcessingException e) {
e.printStackTrace();
return null;
}
});
Multi<String> customersMulti = generatedCustomer
.skip().last().map( s -> s + "," );
Multi<String> lastMulti = generatedCustomer
.select().last();
return customersMulti.onCompletion().switchTo(lastMulti);
} catch (Exception e) {
throw new CustomerException("Exception occurred during the generation of Customer : " + e);
}
}
You can find more information in the documentation
The following is something I tried and it worked:
public static Multi < String > generate(final Input input) {
final ObjectMapper objectMapper = new ObjectMapper();
try {
final Multi < String > beginDocument = Multi.createFrom().items("\"isA\":\"customerDocument\", \"creationDate\":\"" + Instant.now().toString() + "\", \"customerBody\":{ \"customerList\":[");
final AtomicBoolean firstEntry = new AtomicBoolean(true);
final Multi < String > generatedCustomer = Multi.createFrom().publisher(CustomerGenerator.createModels(input)).onItem().transform(
event - > {
try {
if (firstEntry.getAndSet(false)) {
return objectMapper
.writerWithDefaultPrettyPrinter()
.writeValueAsString(event);
}
return "," +
objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(event);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
});
return Multi.createBy().concatenating().streams(beginDocument, generatedCustomer, Multi.createFrom().items("]}}"));
} catch (Exception e) {
throw new CustomerException("Exception occurred during the generation of Customer : " + e);
}
}
I'm trying to append JSONObjects inside a JSONArray that is called Records .
The first time I save it it saves it this way that is ok
{
"Records": [
{
"travelTime": 2,
"totalDistance": 0,
"pace": 0,
"kCalBurned": 0,
"latlng": "[lat\/lng: (-32.1521234,-63.66412321)]"
}
]
}
But when I try to append again a new jsonobject inside Records, it creates a new JSONArray for it, and I just want to append a new object inside records
{
"Records": [
{
"travelTime": 2,
"totalDistance": 0,
"pace": 0,
"kCalBurned": 0,
"latlng": "[lat\/lng: (-31.6432292,-63.3667462)]"
}
]
}{
"Records": [
{
"travelTime": 1,
"totalDistance": 0,
"pace": 0,
"kCalBurned": 0,
"latlng": "[lat\/lng: (-31.9522431,-64.3461241)]"
}
]
}
This is the code I use to save the Records
private void writeJsonData(long travelTime,float totalDistance, float pace, float kCalBurned, LinkedList<LatLng> latlng){
String jsonStr = "";
JSONObject records = new JSONObject();
try {
records.put("travelTime", travelTime);
records.put("totalDistance", totalDistance);
records.put("pace", pace);
records.put("kCalBurned", kCalBurned);
records.put("latlng", latlng);
JSONArray jsonArray = new JSONArray();
jsonArray.put(records);
JSONObject recordsObj = new JSONObject();
recordsObj.put("Records", jsonArray);
jsonStr = recordsObj.toString();
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String file_name = "records.json";
FileOutputStream fileOutputStream = null;
try {
fileOutputStream = new FileOutputStream(new File(mContext.getFilesDir(),file_name),true);
fileOutputStream.write(jsonStr.getBytes());
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
You need a JSON parser so that you can locate the "Records" array inside the file and place the new data there. I used the "json simple" library (jar can be found here: https://code.google.com/archive/p/json-simple/downloads).
First you parse the file:
JSONParser parser = new JSONParser();
JSONObject records = null;
try {
records = (JSONObject) parser.parse(new FileReader("records.json"));
} catch (ParseException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
Then you locate the Records JSONArray. In there you want to append the new record:
JSONArray r = (JSONArray) records.get("Records");
Create the new record:
JSONObject NewObj = new JSONObject();
NewObj.put("travelTime", travelTime);
NewObj.put("totalDistance", totalDistance);
NewObj.put("pace", pace);
NewObj.put("kCalBurned", kCalBurned);
NewObj.put("latlng", latlng);
Add the new record to the "Records" JSONArray:
r.add(NewObj);
Write to file:
try (FileWriter file = new FileWriter("records.json")) {
file.write(records.toJSONString());
} catch (IOException ex) {
ex.printStackTrace();
}
Passing 2nd parameter to true in FileOutputStream constructor will
append jsonObject at the end of file.
To append it with JSON array inside Records object, you've to read the file first, append the new JSON object and write it back to file.
Use GSON library for conversion between java class & jSON. So you don't have to create JSON object manually each time by putting each key-pair.
Create a Java class to hold whole Records object
public class Record
{
#SerializedName("Records")
private List<Object> recordsList;
public Record()
{
this. recordsList = new ArrayList<>();
}
public List<Object> getRecordsList()
{
return recordsList;
}
}
Now create JAVA Model class to hold travel info
public class Travel {
private Integer travelTime;
private Integer totalDistance;
private Integer pace;
private Integer kCalBurned;
private LinkedList<LatLng> latlng;
public Integer getTravelTime() {
return travelTime;
}
public void setTravelTime(Integer travelTime) {
this.travelTime = travelTime;
}
public Integer getTotalDistance() {
return totalDistance;
}
public void setTotalDistance(Integer totalDistance) {
this.totalDistance = totalDistance;
}
public Integer getPace() {
return pace;
}
public void setPace(Integer pace) {
this.pace = pace;
}
public Integer getKCalBurned() {
return kCalBurned;
}
public void setKCalBurned(Integer kCalBurned) {
this.kCalBurned = kCalBurned;
}
public LinkedList<LatLng> getLatlng() {
return latlng;
}
public void setLatlng(LinkedList<LatLng> latlng) {
this.latlng = latlng;
}
}
Here is utility class with a function to append new JSON inside Records object. It will check if directory & file are created otherwise will create both.If file exist, it will read the file, append the new JSON object to list and write it back into the same file. You can change the directory & file name with yours.
Note: This class is written in Kotlin. Here is reference how to setup Android Studio for Kotlin
class Logger {
companion object {
private const val LOG_FILE_FOLDER = "Logs"
private const val LOG_FILE_NAME = "transaction"
private const val DATE_FORMAT = "yyyy-MM-dd"
private val logFileName: String
#SuppressLint("SimpleDateFormat")
get() {
var fileName = LOG_FILE_NAME
val dateFormat = SimpleDateFormat(DATE_FORMAT)
fileName += "_" + dateFormat.format(Date()) + ".json"
return fileName
}
fun logFile(json: Any) {
try {
val directoryPath = Environment.getExternalStorageDirectory().path + "/" + LOG_FILE_FOLDER
val loggingDirectoryPath = File(directoryPath)
var loggingFile = File("$directoryPath/$logFileName")
if (loggingDirectoryPath.mkdirs() || loggingDirectoryPath.isDirectory) {
var isFileReady = true
var isNewFile = false
if (!loggingFile.exists()) {
isFileReady = false
try {
loggingFile.createNewFile()
isNewFile = true
isFileReady = true
} catch (e: Exception) {
e.printStackTrace()
}
} else {
val lastFile = getLastFile(loggingFile.name, directoryPath)
loggingFile = File("$directoryPath/$lastFile")
val fileSize = getFileSize(loggingFile)
}
if (isFileReady) {
var jsonString: String? = null
if (!isNewFile) {
//Get already stored JsonObject
val stream = FileInputStream(loggingFile)
try {
val fileChannel = stream.channel
val mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fileChannel.size())
jsonString = Charset.defaultCharset().decode(mappedByteBuffer).toString()
} catch (e: Exception) {
e.printStackTrace()
} finally {
stream.close()
}
}
//Create record object
val record = if (!jsonString.isNullOrEmpty()) {
Gson().fromJson(jsonString, Record::class.java)
} else {
Record()
}
//Append the current json
record.recordList.add(json)
//create json to save
val jsonToSave = Gson().toJson(record)
val bufferedOutputStream: BufferedOutputStream
try {
bufferedOutputStream = BufferedOutputStream(FileOutputStream(loggingFile))
bufferedOutputStream.write(jsonToSave.toByteArray())
bufferedOutputStream.flush()
bufferedOutputStream.close()
} catch (e4: FileNotFoundException) {
e4.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
} finally {
System.gc()
}
}
}
} catch (ex: Exception) {
ex.printStackTrace()
}
}
}
}
At the end, you can log the file withlogFile method
Logger.Companion.logFile(travel);
Cheers :)
I have a list of information returned from the server and I am putting it in arraylist called "items". I would like to know how I can extract just the departments and place them into a simple string array which I have named department list .
This is what the list looks like
[
{
"Department": "Mobile Development",
"Department": 22
},
{
" "Department": "IT Support",
"Department": 13
}]
This is what I have coded so far however I think there is a problem with the way I am trying to add in my for each .
private void loadCompanyInfo() {
//final Context context = this.getActivity();
final Context context = this.context;
Organization client = new Organization(context);
Organization.api(context).getCompanyInforamtion(client.getID()).enqueue(new Callback<Results<CostCentresResult>>() {
#Override
public void onResponse(Call<Results<CostCentresResult>> call, Response<Results<CostCentresResult>> response) {
if (response.isSuccessful()) {
try {
Items = new ArrayList<>();
companyInfoList = new ArrayList<>();
Items.addAll(response.body());
if(Items.contains("Department")) {
Items.get(Items.indexOf(0));
for (int i = 0; i < Items.size(); i++) {
companyInfoList.add(Items[0])
}
}
} catch (Exception ex ) {
ex.printStackTrace();
ex.getMessage();
ex.getCause();
ex.getClass();
}
}
}
#Override
public void onFailure(Call<Results<CostCentresResult>> call, Throwable t) {
// TODO: handle ex
Errors.handleException(t);
}
});
}
}
Following code will help you to get the list of department from your server response:
try {
ArrayList<String> mDepartmentList = new ArrayList<String>();
JSONArray serverResponseJsonArray = new JSONArray(response.body());
if (serverResponseJsonArray != null
&& serverResponseJsonArray.length() > 0) {
for (int i = 0; i < serverResponseJsonArray.length(); i++) {
JSONObject departmentJsonObj = serverResponseJsonArray
.getJSONObject(i);
if (departmentJsonObj != null
&& !departmentJsonObj.equals("")) {
if (departmentJsonObj.has("Department")) {
mDepartmentList.add(departmentJsonObj
.getString("Department"));
}
}
}
}
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
I am trying this to toggle the value of key1 in but I get the same value all the time. What am I doing wrong here?
boolean jsonText = true;
JSONObject jsonObj = new JSONObject();
public void setjsonObject(boolean val){
this.jsonText = val;
}
public Boolean getjsonObject(){
return this.jsonText;
}
#POST("/hello")
#PermitAll
public String hello(String text) {
try {
if (jsonObj.has("key1")) {
boolean val = !jsonObj.getBoolean("key1");
jsonObj.remove("key1");
jsonObj.put("key1", val);
} else {
jsonObj.put("key1", true);
}
} catch (JSONException e) {
e.printStackTrace();
}
return "some result";
}
Am I resetting the "key1" boolean value somewhere?
you are creating new JSON object every time:
JSONObject jsonObj = new JSONObject();
so it never has any value for "key1" and it is always set to true after your hello code.
I cant change the mapping. Can anybody help me to find the bug in my code?
I have found this standard way to change the mapping according to several tutorials. But when i'm try to call the mapping structure there just appear a blank mapping structure after manuall mapping creation.
But after inserting some data there appear the mapping specification because ES is using of course the default one. To be more specific see the code below.
public class ElasticTest {
private String dbname = "ElasticSearch";
private String index = "indextest";
private String type = "table";
private Client client = null;
private Node node = null;
public ElasticTest(){
this.node = nodeBuilder().local(true).node();
this.client = node.client();
if(isIndexExist(index)){
deleteIndex(this.client, index);
createIndex(index);
}
else{
createIndex(index);
}
System.out.println("mapping structure before data insertion");
getMappings();
System.out.println("----------------------------------------");
createData();
System.out.println("mapping structure after data insertion");
getMappings();
}
public void getMappings() {
ClusterState clusterState = client.admin().cluster().prepareState()
.setFilterIndices(index).execute().actionGet().getState();
IndexMetaData inMetaData = clusterState.getMetaData().index(index);
MappingMetaData metad = inMetaData.mapping(type);
if (metad != null) {
try {
String structure = metad.getSourceAsMap().toString();
System.out.println(structure);
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void createIndex(String index) {
XContentBuilder typemapping = buildJsonMappings();
String mappingstring = null;
try {
mappingstring = buildJsonMappings().string();
} catch (IOException e1) {
e1.printStackTrace();
}
client.admin().indices().create(new CreateIndexRequest(index)
.mapping(type, typemapping)).actionGet();
//try put mapping after index creation
/*
* PutMappingResponse response = null; try { response =
* client.admin().indices() .preparePutMapping(index) .setType(type)
* .setSource(typemapping.string()) .execute().actionGet(); } catch
* (ElasticSearchException e) { e.printStackTrace(); } catch
* (IOException e) { e.printStackTrace(); }
*/
}
private void deleteIndex(Client client, String index) {
try {
DeleteIndexResponse delete = client.admin().indices()
.delete(new DeleteIndexRequest(index)).actionGet();
if (!delete.isAcknowledged()) {
} else {
}
} catch (Exception e) {
}
}
private XContentBuilder buildJsonMappings(){
XContentBuilder builder = null;
try {
builder = XContentFactory.jsonBuilder();
builder.startObject()
.startObject("properties")
.startObject("ATTR1")
.field("type", "string")
.field("store", "yes")
.field("index", "analyzed")
.endObject()
.endObject()
.endObject();
} catch (IOException e) {
e.printStackTrace();
}
return builder;
}
private boolean isIndexExist(String index) {
ActionFuture<IndicesExistsResponse> exists = client.admin().indices()
.exists(new IndicesExistsRequest(index));
IndicesExistsResponse actionGet = exists.actionGet();
return actionGet.isExists();
}
private void createData(){
System.out.println("Data creation");
IndexResponse response=null;
for (int i=0;i<10;i++){
Map<String, Object> json = new HashMap<String, Object>();
json.put("ATTR1", "new value" + i);
response = this.client.prepareIndex(index, type)
.setSource(json)
.setOperationThreaded(false)
.execute()
.actionGet();
}
String _index = response.getIndex();
String _type = response.getType();
long _version = response.getVersion();
System.out.println("Index : "+_index+" Type : "+_type+" Version : "+_version);
System.out.println("----------------------------------");
}
public static void main(String[] args)
{
new ElasticTest();
}
}
I just wanna change the property of ATTR1 field to analyzed to ensure fast queries.
What im doing wrong? I also tried to create the mapping after index creation but it leads to the same affect.
Ok i found the answer by my own. On the type level i had to wrap the "properties" with the type name. E.g:
"type1" : {
"properties" : {
.....
}
}
See the following code:
private XContentBuilder getMappingsByJson(){
XContentBuilder builder = null;
try {
builder = XContentFactory.jsonBuilder().startObject().startObject(type).startObject("properties");
for(int i = 1; i<5; i++){
builder.startObject("ATTR" + i)
.field("type", "integer")
.field("store", "yes")
.field("index", "analyzed")
.endObject();
}
builder.endObject().endObject().endObject();
}
catch (IOException e) {
e.printStackTrace();
}
return builder;
}
It creates mappings for the attributes ATTR1 - ATTR4. Now it is possible to define mapping for Example a list of different attributes dynamically. Hope it helps someone else.