i have a response from a GET (String) and i try to convert this String to XML File using Kotlin.
I try this :
fun convertStringToXml(): Document?
{
val xmlStr = getResponseMedium()
val doc: Document? = convertStringToDocument(xmlStr)
return doc
}
private fun convertStringToDocument(xmlStr: String): Document?
{
val factory = DocumentBuilderFactory.newInstance()
val builder: DocumentBuilder
try
{
builder = factory.newDocumentBuilder()
return builder.parse(InputSource(StringReader(xmlStr)))
} catch (e: Exception)
{
e.printStackTrace()
}
return null
}
The String look like that :
<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
<channel>
<title><![CDATA[Stories by XXX on Medium]]></title>
<description><![CDATA[Stories by XXX on Medium]]></description>
<link>https://medium.com/#XXX?source=rss-f2a3ce60be14------2</link>
<image>
<url>https://cdn-images-1.medium.com/fit/c/150/150/1*J89zHB-oSfsAFzzXOLnP_g#2x.jpeg</url>
<title>Stories by XXX on Medium</title>
<link>https://medium.com/#XXX?source=rss-f2a3ce60be14------2</link>
</image>
And the result of my Document is null
Any idea ?
Thanks !
Related
Can I convert data when parsing it from json to MutableLiveData and how if it's possible?
#TypeConverter
fun stringToDatas(string: String) :MutableLiveData<HashMap<String,Any>> {
val liveData = object : TypeToken<MutableLiveData<HashMap<String, Any>>>() {
//here i guess should return it.
//and how can i return it from string to MutableLiveData
}.type
return Gson().fromJson(string, liveData)
}
Thank you.
It could be done this way
#TypeConverter
fun stringToDatas(string: String) :MutableLiveData<HashMap<String,Any>> {
val map= object : TypeToken<HashMap<String, Any>>() {}.type
return MutableLiveData<HashMap<String,Any>>(Gson().fromJson(string, map))
}
UPDATE
#TypeConverter
fun datasToString(liveData: MutableLiveData<HashMap<String,Any>>): String {
return gson.toJson(liveData.value)
}
I'm trying to do a post request in Android Studio written in Kotlin
I'm posting a JSON object to our server and then the server is returning a JSON object back. But what I'm doing here is decoding the response body as a string and then converting it into the data structure we need. I'm sure there is a better and simpler way to do what I need done.
My current code works but the major issue I'm having is formatting the string if our objects have nested objects which is why I want to figure out a better way to turn the response body into a json object.
I'm not too familiar with many request libraries for kotlin but I have looked into okhttp3 but I'm not sure how to post a json object, attach headers and decode the response body into a json object.
I know for okhttp3 I need to convert the json object to a string to post other than that I'm lost.
Breakdown of what's needed:
Post JSON Object To Server
Send Headers With Post Request
Decode Response Body into JSON Object/ Kotlin Equivalent
Simplify What I'm Trying to Do if Possible
This is the current code I have
private fun postRequestToGetDashboardData() {
val r = JSONObject()
r.put("uid", muid)
r.put("token", mtoken)
SendJsonDataToServer().execute(r.toString());
}
inner class SendJsonDataToServer :
AsyncTask<String?, String?, String?>() {
override fun onPostExecute(result: String?) {
super.onPostExecute(result)
if (result.equals(null)) {
val t = Toast.makeText(this#Home, "No devices to display", Toast.LENGTH_LONG)
t.setGravity(Gravity.CENTER, 0, 0)
t.show()
} else {
intentForUnique.putExtra("FirstEndpointData", result)
var list = handleJson(result)
adapter.submitList(list)
dashboardItem_list.adapter = adapter
adapter.notifyDataSetChanged();
dashboardItem_list.smoothScrollToPosition(0);
}
}
override fun doInBackground(vararg params: String?): String? {
val JsonDATA = params[0]!!
var urlConnection: HttpURLConnection? = null
var reader: BufferedReader? = null
try {
val url = URL("URL");
urlConnection = url.openConnection() as HttpURLConnection;
urlConnection.setDoOutput(true);
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Type", "application/json");
urlConnection.setRequestProperty("Authorization", mtoken);
urlConnection.setRequestProperty("Accept", "application/json");
val writer: Writer =
BufferedWriter(OutputStreamWriter(urlConnection.getOutputStream(), "UTF-8"));
writer.write(JsonDATA);
writer.close();
val inputStream: InputStream = urlConnection.getInputStream();
if (inputStream == null) {
return null;
}
reader = BufferedReader(InputStreamReader(inputStream))
var inputLine: String? = reader.readLine()
if (inputLine.equals("null")) {
return null
} else {
return inputLine
}
} catch (ex: Exception) {
Log.e(TAG, "Connection Failed", ex);
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
if (reader != null) {
try {
reader.close();
} catch (ex: Exception) {
Log.e(TAG, "Error closing stream", ex);
}
}
}
return null
}
}
private fun handleJson(jsonString: String?): ArrayList<SensorData> {
val jsonArray = JSONArray(jsonString)
val list = ArrayList<SensorData>()
var x = 0
while (x < jsonArray.length()) {
val jsonObject = jsonArray.getJSONObject(x)
list.add(
SensorData(
jsonObject.getInt("deviceId"),
// jsonObject.getString("deviceName"),
jsonObject.getInt("battery"),
jsonObject.getString("dateTime"),
jsonObject.getInt("airValue"),
jsonObject.getInt("waterValue"),
jsonObject.getInt("soilMoistureValue"),
jsonObject.getInt("soilMoisturePercent")
)
)
x++
}
return list
}
So the json data being returned back is an array of this structure (our backend is written in Go)
type Device struct {
DeviceID int `bson:"deviceId" json:"deviceId"`
Battery int `bson:"battery" json:"battery"`
DateTime time.Time `bson:"dateTime" json:"dateTime"`
AirValue int `bson:"airValue" json:"airValue"`
WaterValue int `bson:"waterValue" json:"waterValue"`
SoilMoistureValue int `bson:"soilMoistureValue" json:"soilMoistureValue"`
SoilMoisturePercent int `bson:"soilMoisturePercent" json:"soilMoisturePercent"`
}
I'm trying to parse JSON data to a class but gson.fromJson(response, bitt::class.java) keeps returning null.
class bitt(#SerializedName("result")val result: String) {
val someVal: String = "string"
fun method() {
print("something")
}
}
val response: String = "{'success':true,'message':'','result':'Im a sult'}"
println(response)
val gson = Gson()
val ticker = gson.fromJson(response, bitt::class.java)
println(ticker)
What am I doing wrong here?
JSON always uses double quotes ", not single quotes '. Your response uses single quotes, so it is not valid JSON.
As in many other languages, you can use \" to put a double quote in a string literal:
val response: String = "{\"success\":true,\"message\":\"\",\"result\":\"I'm a result\"}"
change to Data Class instead of Class
example from your code:
data class bitt(val result: String = "") {
val someVal: String = "string"
fun method() {
print("something")
}
}
I guess it takes long time before you get the result back
so the ticker still remain null
you can use kotlin coroutines to handle it.
or simply use callback like this
data class bitt(val result: String = "") {
val someVal: String = "string"
fun method() {
print("something")
}
}
fun getTicker(response: String, onComplete: (bitt) -> Unit) {
val ticker = Gson().fromJson(response, bitt::class.java)
onComplete(ticker)
}
val response: String = "{'success':true,'message':'','result':'Im a sult'}"
println(response)
getTicker(response){ println(it) }
then you might need to use Coroutine
https://github.com/Kotlin/kotlinx.coroutines
data class bitt(val result: String = "") {
val someVal: String = "string"
fun method() {
print("something")
}
}
suspend fun getTicker(response: String) = Gson().fromJson(response, bitt::class.java)
fun yourMethod() {
val response: String = "{'success':true,'message':'','result':'Im a sult'}"
println(response)
CoroutineScope(IO).launch {
val ticker = getTicker(response)
println(ticker)
}
}
KotlinConf 2017 - Introduction to Coroutines by Roman Elizarov
I am working on trying to parse some XML data to a tableView and I keep coming up with my string being empty, thus not allowing me to populate a tableView. I have checked all over online trying to find good example on how to achieve this but everything seems to be out of date due to swift changing all the time.
<?xml version="1.0" encoding="UTF-8"?>
<client region = "Midwest">
<person
name = "Pete Seeger"
profession = "Musician"
dob = "May 3, 1919">
<child
name = "Daniel">
</child>
<child
name = "Mika">
</child>
<child
name = "Tinya">
</child>
</person>
</client>
Next is my Client.swift file
class Client{
var clientName: String = String()
var clientProfession: String = String()
var clientDob: String = String()}
and in my ViewController I have declared these variables
var client: [Client] = []
var eName: String = String() //element Name
var cName: String = String()
var cProfession: String = String()
var cDOB: String = String()
Preceding is my didStart/didEnd/and foundCharacters
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
//this finds the starting tag of <person>
eName = (elementName as NSString) as String
if eName == "person"{
print("we found start tag of person")
cName = String()
cProfession = String()
cDOB = String()
}
func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?)
{
//this looks for the end tag </person>
if eName == "person"{
print("we found End tag of person")
let client = Client() //letting the client = to w.e
print(client, "printing client in the didEndElement")
client.clientName = cName
print(cName, "This is the cName though nothing will show I bet...")
client.clientProfession = cProfession
client.clientDob = cDOB
}
func parser(_ parser: XMLParser, foundCharacters string: String)
{
let foundChar = string.trimmingCharacters(in: NSCharacterSet.whitespacesAndNewlines)
print(foundChar, "This is foundChar for foundCharacters")
if(foundChar.isEmpty){
print("its empty")
}
else{
if eName == "name"{
cName += foundChar
cProfession += foundChar
cDOB += foundChar
}
}
I am finding the beginning tags and closing tags for person, but once it gets to the foundCharacters it seems that it is returning empty. Am I overlooking something here?
You are looking for your data at the wrong place.
parser(_:foundCharacters:) function is getting called for text that is in between open and close tags.
For the following example XML:
<name>Pete Seeger</name>
parser(_:foundCharacters:) function will be called with foundCharacters = "Pete Seeger"
The data that you are looking for is in element's attributes. Just check the attributeDict parameter in parser(_:didStartElement:namespaceURI:qualifiedName:attributes:) function.
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
//this finds the starting tag of <person>
eName = (elementName as NSString) as String
if eName == "person"{
print("we found start tag of person")
cName = attributeDict["name"] ?? ""
cProfession = attributeDict["profession"] ?? ""
cDOB = attributeDict["dob"] ?? ""
}
}
Also, if you are interesting in mapping the XML into swift objects consider XMLMapper. (uses the same technique as the ObjectMapper)
Hope this helps.
I'm trying to write a null-safe String adapter that will serialize this JSON {"nullString": null} into this: Model(nullString = "") so that any JSON with a 'null' value that I expect to be a String will be replaced with "" (assuming there exists a data class like this: data class Model(val nullString: String))
I wrote a custom adapter to try and handle this:
class NullStringAdapter: JsonAdapter<String>() {
#FromJson
override fun fromJson(reader: JsonReader?): String {
if (reader == null) {
return ""
}
return if (reader.peek() == NULL) "" else reader.nextString()
}
#ToJson
override fun toJson(writer: JsonWriter?, value: String?) {
writer?.value(value)
}
}
...in an attempt to solve this parsing error:
com.squareup.moshi.JsonDataException: Expected a name but was NULL at path $.nullString
Moshi parsing code:
val json = "{\"nullString\": null}"
val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.add(NullStringAdapter())
.build()
val result = moshi.adapter(Model::class.java).fromJson(configStr)
What am I missing here? Still new to moshi so any help is appreciated!
The immediate problem is the missing reader.nextNull() call to consume the null value.
There are a couple other cleanup things you can do here, too.
With #FromJson, implementing JsonAdapter is unnecessary.
Also, the JsonReader and JsonWriter are not nullable.
object NULL_TO_EMPTY_STRING_ADAPTER {
#FromJson fun fromJson(reader: JsonReader): String {
if (reader.peek() != JsonReader.Token.NULL) {
return reader.nextString()
}
reader.nextNull<Unit>()
return ""
}
}
and use add the adapter:
val moshi = Moshi.Builder()
.add(NULL_TO_EMPTY_STRING_ADAPTER)
.add(KotlinJsonAdapterFactory())
.build()