I tried convert to data class to map. (Under the code is just example code)
data class User (
val name : String = "",
val age : Int = 0,
val deviceGroup: MutableSet<DeviceGroup> = mutableSetOf()
)
data class DeviceGroup (
val name : String = "",
val deviceLink : MutableSet<DeviceLink> = mutableSetOf()
)
data class DeviceLink (
val id : Int = 0,
val device : Device
)
data class Device (
val devId : Int = 0,
val name : String = ""
)
fun main (request : HttpServletRequest) {
val currentUser = request.session.getAttribute("user") as User
val data = userRepository.findByName(currentUser.name)
// return currentUser
// result is {name="test", age=17, deviceGroup = [{name="group1"}, {name="group2"}]}
// I want deserialization data class to Map
val response = data.deviceGroup.toMap()
response.deivceGroup.forEach {
// And add new key, pair
it.add(Map<String, MutableSet<Device>>("devices", mutableSetOf()))
// Lastly, I want put in the value
deviceGroupRepository.findByName(it.name).deviceLink.forEach {
it.devices.add(this)
}
}
return response
}
if just return the data value, that's result is "{name="test", age=17, deviceGroup = [{name="group1"}, {name="group2"}]}"
How to convert to data class to Map object and add new key pair?
Use associate to turn a collection into a Map
The Kotlin standard library provides a function called associate which will take a collection of objects and transform them into a map. It takes one argument, which is a function specifying what the keys and values of the map should be.
For example, in your case, you would call it like this:
val response = data.deviceGroup.associate { it.name to it.deviceLink }
It will return a Map<String, MutableSet<DeviceLink>> where the key is the name of the device group and the value is the deviceLink set.
The easiest way to add new values is simply to append them with the + operator.
val response = data.deviceGroup.associate {
it.name to it.deviceLink
} + mapOf("device" to emptySet())
If you need more control than that, you could use .toMutableMap() so new entries can be added using put.
val response = data.deviceGroup.associate {
it.name to it.deviceLink
}.toMutableMap()
response.put("device", emptySet())
I have parent class and some childs class and when i save the data in The data base i receive the Id of the attribute not the content of it .Here's the classes that i have:
class Address(object):
def __init__(self,RealEstate_Adress=None, RealEstate_Zip_Code=None):
self.RealEstate_Adress = RealEstate_Adress
self.RealEstate_Zip_Code = RealEstate_Zip_Code
class Webads( object):
def __init__(self, type=None, titre=None):
self.Type = type
self.Title = titre
self.Adress = Address()
and here i'm making an instance for each class :
add = Address()
add.RealEstate_Adress = item["RealEstate_Adress"]
add.RealEstate_Zip_Code = item["RealEstate_zip"]
web = Webads()
web.Title = item["RealEstate_title"]
web.Type = item["RealEstate_type"]
web.Adress = add
and here i'm saving it as json :
json_to_save = json.dumps(web.__dict__, default=str)
but when i run it i get in the address something like this :
"Adress": "<__mp_main__.Address object at 0x0000013DCB13CE80>",
and i want it to be like this :
{
"Type": "Appartement",
"Title": "appartement 2 pièces",
"Adress":{
"Realestate_Adress":"paris 15"
"Realestate_zip_code":"75015"
}
}
You could use dictionaries instead of classes:
web = {
'Title': item["RealEstate_title"],
'Type': item["RealEstate_type"],
'Adress': {
'RealEstate_Adress': item["RealEstate_Adress"],
'RealEstate_Zip_Code': item["RealEstate_zip"],
},
}
JSON Data Parsing Using Retofit2 and Rxjava2. This Data get In ArrayList successfully. its ArrayList Size is Nine but its display only two Record in Table. After Two Record its Kotlin.NullPointerException.
JSON Data:
{"success":1,"salesGst":[{"Cmp_Name":"ABC","GSTIN":"AAAA","FirmName":"SALES GJ","ChallanNo":"1","ChallanDate":"2019-03-15 00:00:00","ChallanAmount":"2778.75","TaxTotal":"2778.75","InvoiceType":"Retail Invoice","CGSTTotal":"0.0","PartyGST":"CDE","SGSTTotal":"0.0","IGSTTotal":"0.0"},{"Cmp_Name":"ABC","GSTIN":"AAAA","FirmName":"SALES GJ","ChallanNo":"1","ChallanDate":"2019-03-13 00:00:00","ChallanAmount":"2203.0","TaxTotal":"2118.5","InvoiceType":"Tax Invoice","CGSTTotal":"52.96","PartyGST":"CDE","SGSTTotal":"52.96","IGSTTotal":"0.0"},{"Cmp_Name":"ABC","GSTIN":"AAAA","FirmName":"VIKAS","ChallanNo":"2","ChallanDate":"2019-03-16 00:00:00","ChallanAmount":"6975.0","TaxTotal":"6975.0","InvoiceType":"Retail Invoice","CGSTTotal":"0.0","PartyGST":null,"SGSTTotal":"0.0","IGSTTotal":"0.0"},{"Cmp_Name":"ABC","GSTIN":"AAAA","FirmName":"SALES MH","ChallanNo":"2","ChallanDate":"2019-03-13 00:00:00","ChallanAmount":"420.0","TaxTotal":"403.75","InvoiceType":"Tax Invoice","CGSTTotal":"0.0","PartyGST":"ABC","SGSTTotal":"0.0","IGSTTotal":"20.19"},{"Cmp_Name":"ABC","GSTIN":"AAAA","FirmName":"SALES GJ","ChallanNo":"3","ChallanDate":"2019-03-14 00:00:00","ChallanAmount":"4788.0","TaxTotal":"4560.0","InvoiceType":"Tax Invoice","CGSTTotal":"114.0","PartyGST":"CDE","SGSTTotal":"114.0","IGSTTotal":"0.0"},{"Cmp_Name":"ABC","GSTIN":"AAAA","FirmName":"SALES GJ","ChallanNo":"4","ChallanDate":"2019-03-15 00:00:00","ChallanAmount":"241.9","TaxTotal":"230.38","InvoiceType":"Tax Invoice","CGSTTotal":"5.76","PartyGST":"CDE","SGSTTotal":"5.76","IGSTTotal":"0.0"},{"Cmp_Name":"ABC","GSTIN":"AAAA","FirmName":"SALES GJ","ChallanNo":"5","ChallanDate":"2019-03-15 00:00:00","ChallanAmount":"5563.68","TaxTotal":"5101.5","InvoiceType":"Tax Invoice","CGSTTotal":"231.28","PartyGST":"CDE","SGSTTotal":"231.28","IGSTTotal":"0.0"},{"Cmp_Name":"ABC","GSTIN":"AAAA","FirmName":"SALES GJ","ChallanNo":"6","ChallanDate":"2019-03-16 00:00:00","ChallanAmount":"13238.0","TaxTotal":"12459.25","InvoiceType":"Tax Invoice","CGSTTotal":"389.29","PartyGST":"CDE","SGSTTotal":"389.29","IGSTTotal":"0.0"},{"Cmp_Name":"ABC","GSTIN":"AAAA","FirmName":"SALES MH","ChallanNo":"7","ChallanDate":"2019-03-16 00:00:00","ChallanAmount":"2074.0","TaxTotal":"1975.0","InvoiceType":"Tax Invoice","CGSTTotal":"0.0","PartyGST":"ABC","SGSTTotal":"0.0","IGSTTotal":"98.75"}]}
Please Guide Me,After Getting How to Show in TableLayout.
In ArrayList Nine Record but in Table show only Two Record another seven record is not display. in third record taxtotal give kotlin.nullpointerException. what missing?
private fun displaySalesGSTData(salesGSt : List<SalesGST>) {
salesGST = SalesGST()
tvSalesCompanyName.setText(salesGSt.get(1).Cmp_Name)
tvGSTIN.setText(salesGSt.get(1).GSTIN)
val rowHeader = TableRow(this#Sales)
rowHeader.setBackgroundColor(Color.parseColor("#c0c0c0"))
rowHeader.setLayoutParams(TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.WRAP_CONTENT))
val headerText = arrayOf<String>("Sr.No.", "Invoice Type", "Bill No.", "Bill Date", "Firm Name", "GST NO","TAX Total","CGST","SGST","IGST","Net Amount")
for (c in headerText)
{
val tv = TextView(this#Sales)
tv.setLayoutParams(TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT,
TableRow.LayoutParams.WRAP_CONTENT))
tv.setGravity(Gravity.CENTER)
// tv.setBackgroundResource(R.drawable.table_header)
tv.setTextColor(Color.parseColor("#3F51B5"))
tv.setTextSize(18F)
tv.setPadding(5, 5, 5, 5)
tv.setText(c)
rowHeader.addView(tv)
}
tableMarks.addView(rowHeader)
for (j in 0 until salesGSt.size)
{
/*val jsonObject1 = jsonArray.getJSONObject(j)
val date = jsonObject1.getString("ExamDate")
val inputFormatter1 = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
val date1 = inputFormatter1.parse(date)
val outputFormatter1 = SimpleDateFormat("dd-MMM-yyyy")
ExamDate = outputFormatter1.format(date1)*/
/* String replaceDate = date.replace("/Date(", "").replace(")/", "");
Long getDate = Long.valueOf(replaceDate);
ExamDate = dateFormat.format(getDate);*/
/*Subject = jsonObject1.getString("subject")
ExamName = jsonObject1.getString("ExamName")
TotalMark = jsonObject1.getLong("TotalMarks")
PassingMark = jsonObject1.getLong("PassingMarks")
Mark = jsonObject1.getLong("Marks")*/
var fName : String = salesGSt.get(j).FirmName!!
var invoice : String = salesGSt.get(j).InvoiceType!!
var bill_no : String = salesGSt.get(j).ChallanNo!!
var bill_date : String = salesGSt.get(j).ChallanDate!!
var gst_no : String = salesGSt.get(j).PartyGST!!
var tax_total : Double = salesGSt.get(j).TaxTotal!!.toDouble()
var cgst : String = salesGSt.get(j).CGSTTotal!!
var igst : String = salesGSt.get(j).IGSTTotal!!
var sgst : String = salesGSt.get(j).SGSTTotal!!
var net_amount : String = salesGSt.get(j).ChallanAmount!!
var sr : Int = j + 1
// dara rows
val row = TableRow(this#Sales)
row.setLayoutParams(TableLayout.LayoutParams(TableLayout.LayoutParams.MATCH_PARENT,
TableLayout.LayoutParams.WRAP_CONTENT))
val colText = arrayOf<String>(sr.toString(),(invoice), bill_no, bill_date, fName, gst_no, tax_total.toString(),cgst,sgst,igst,net_amount)
for (text in colText)
{
val tv = TextView(this#Sales)
tv.setLayoutParams(TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT,
TableRow.LayoutParams.WRAP_CONTENT))
tv.setGravity(Gravity.CENTER)
// tv.setBackgroundResource(R.drawable.table_shape)
tv.setTextSize(18F)
tv.setTextColor(Color.parseColor("#3F51B5"))
tv.setPadding(5, 5, 5, 5)
tv.setText(text)
row.addView(tv)
}
tableMarks.addView(row)
}
}
The 3rd item, salesGst[2], is "PartyGST": null. Your json deserializer library won't handle non-null fields as it's written in Java. I assume you have a data class where PartGST is defined as non-null, yet the deserializer will still parse it as null. Therefore, when you access PartyGST then you will receive a NullPointerException because Kotlin is expecting it to be non-null. This is a good article, which explains in more detail:
I've trusted you! You promised no null pointer exceptions!
A solution to this would be to have two models. The DTO (for JSON response) where all fields are optional and your internal model (used by your app), where you define which fields you want to be optional. Then you can have a mapper to handle the case where a field is null in the DTO, but non-null in your internal model:
// Models for your API response
data class SalesGstsDTO(val gsts: List<GstDTO>)
data class GstDTO(val name: String?, val surname: String?)
// Internal models used by your app
data class SalesGsts(val gsts: List<Gst>)
data class Gst(val name: String, val surname: String?)
class SalesGstDTOMapper {
fun mapToSalesGsts(salesGstsDTO: SalesGstsDTO): SalesGsts {
val gsts = mutableListOf<Gst>()
salesGstsDTO.gsts.map {
val name = it.name ?: return#map // Skips this item. You could handle this how you wish
val surname = it.surname
val gst = Gst(name, surname)
gsts.add(gst)
}
return SalesGsts(gsts)
}
}
This also allows you to decouple your app from the JSON response.
creating hard coded json is easy, e.g.
String createJson(Person person, list<Account> accounts) {
def builder = new JsonBuilder()
def json = builder {
person person
accounts accounts
}
return builder.toPrettyString()
}
The above works, and produces something like this:
{
"person":{
username": "user"
"firstName": "test"
}
"accounts":[
{
"balance": "200829.00",
"currency": "CRD",
"id": 1,
}
]
}
The problem is we have a REST api, which returns JSON. Curently, we have a lot of duplicate code, as we can't find a generic way to generate different parts of the JSON api response and combine them together and render the result, ether by merging json strings, or by dynamically buidling the json from a map, e.g the following doesnt work:
String createJson(Map map) {
def builder = new JsonBuilder()
def root = builder {
map.collect { key, value ->
"$key" value
}
}
return builder.toPrettyString()
}
then calling it like this:
Person person = someMethodToGetAPerson()
List<Account> accounts = someMethodToGetAccounts(person)
Map map = ["person", person, "accounts", accounts]
String json = createJson(map)
render(status: 200, contentType: 'application/json', text: json)
However, this fails, with a stack overflow in the bowels of grails.
In addition, we have defined several json marshallers which must be used, e.g.
JSON.registerObjectMarshaller(Account) {
return [balance: formatter.format(it.balance)....
}
Any ideas?
What I could understand is you want to convert a map into JSON string. For that you can use grails.converters.JSON class. For example
Person person = someMethodToGetAPerson()
List<Account> accounts = someMethodToGetAccounts(person)
Map map = [person: person, accounts: accounts]
String json = new JSON(map).toString()
The toString() method also takes an boolean value for preety printing. And it should honor your registered marshallers
I have this example:
def mycreate = {
def id = params.id;
def data = JSON.parse(params.data);
def credit = Credit.get(id);
def front = new Front ();
front.properties = data;
credit.addToFronts(front).save()
render (front as JSON)
}
This action returns something like this:
{"class":"test.Front","id":null,"credits":{"class":"Credit","id":1},"dateCreated":null,"description":"write text here."}
But, for me, the params "id" and "dateCreated" are null. How can I get the values of these params?