I need to make a request to get a token.
If my data isn't correct, i get right answer with "Wrong data"
But if my data is correct, I get an answer:
responseSerializationFailed(reason: Alamofire.AFError.ResponseSerializationFailureReason.inputDataNilOrZeroLength).
But it works on Android version.
Request Code for Android:
#FormUrlEncoded
#POST("api/v1/authorization/login")
fun login(
#Field("username") username: String,
#Field("password") password: String,
#Field("code") code: String
): Single<Response<Void>>
API:
{
"name": "Get token",
"request": {
"method": "POST",
"header": [],
"url": {
"raw": "http://192.168.9.41/api/v1/authorization/login?username=%2B79992402979&password=Qwerty%244&code=4242",
"protocol": "http",
"host": [
"192",
"168",
"9",
"41"
],
"path": [
"api",
"v1",
"authorization",
"login"
],
"query": [
{
"key": "username",
"value": "%2B79992402979"
},
{
"key": "password",
"value": "Qwerty%244"
},
{
"key": "code",
"value": "4242"
}
]
}
},
"response": []
}
My Swift code:
func confirmLoginWithCode(username: String, password: String, code: String, completion: #escaping () -> Void) {
let parameters: Parameters = [
"username": username,
"password": password,
"code": code
]
let url = "\(self.baseUrl)/api/v1/authorization/login"
let authRequest = AF.request(url,
method: .post,
parameters: parameters,
encoding: URLEncoding(destination: .queryString))
authRequest.responseString { (response) in
switch(response.result) {
case .success(let value):
let responseArr = value.components(separatedBy: "\u{0022}")
print(responseArr, "success")
case .failure(let error):
print("\(error) check error")
}
completion()
}
}
Now I realize that my question is pretty useless for the site, but here is my solution:
As it turned out, I just had to look in Header
func confirmLoginWithCode(username: String, password: String, code: String, completion: #escaping () -> Void) {
let parameters: Parameters = [
"username": username,
"password": password,
"code": code
]
let url = "\(self.baseUrl)/api/v1/authorization/login"
let authRequest = AF.request(url,
method: .post,
parameters: parameters,
encoding: URLEncoding(destination: .queryString))
authRequest.responseString { (response) in
switch(response.result) {
case .success(let value):
let responseArr = value.components(separatedBy: "\u{0022}")
if responseArr[31] == "Wrong verification code!" {
self.confirmLoginStatus = .incorrectCode
}
case .failure(let error):
if let receivedHeaders = response.response?.headers.value(for: "Authorization") {
let token = receivedHeaders.replacingOccurrences(of: "Bearer ", with: "")
self.userSettings.token = token
self.confirmLoginStatus = .success
} else {
self.confirmLoginStatus = .connectionError
}
self.errorStatus = error.errorDescription ?? "some error"
}
completion()
}
}
Related
I am always getting the unsuccessful response to my post request using retrofit,
The code is working fine while sending through postman but not while sending
I have tried changing almost every part of it with all the answers available but it doesnt seems to work:
the full error is Response{protocol=h2, code=400, message=, url=https://uatapi.prodigisign.org/api/ChatBotSNS/dsc-upload-video}
My Api is like this
#POST("api/ChatBotSNS/dsc-upload-video")
fun uploadVideo(
#Part("AppNumber") appNumber: RequestBody,
#Part("UserID") userId: RequestBody,
#Part("VideoCode") videoCode: RequestBody,
#Part Video: MultipartBody.Part,
#Part("RecordTimeStamp") recordTimeStamp: RequestBody
): Call<ResponseBody>
My call is like this
val logging = HttpLoggingInterceptor()
logging.level = HttpLoggingInterceptor.Level.BODY
val client = OkHttpClient.Builder()
.addInterceptor(logging)
.build()
val retrofit = Retrofit.Builder()
.baseUrl("https://uatapi.prodigisign.org/")
.addConverterFactory(GsonConverterFactory.create())
.client(client) // add OkHttp client to the Retrofit builder
.build()
val service = retrofit.create(ProdigiSignApi::class.java)
val videoFile = getFileFromUri(this,outputUri)!! // get the video file from the URI
val requestFile = videoFile.asRequestBody("video/webm".toMediaType())
val videoPart = MultipartBody.Part.createFormData("video",videoFile.name, requestFile)
val appNumber = dscData.appNumber.toRequestBody("text/plain".toMediaType())
val userId =
dscData.userid.toRequestBody("text/plain".toMediaType())
val videoCode = dscData.videoCode.toRequestBody("text/plain".toMediaType())
val recordTimeStamp = timestamp.toRequestBody("text/plain".toMediaType())
Log.i("VideoRecordingActivity", "submit: ${videoFile::class.simpleName} $videoFile Path ${videoFile.path}")
val call = service.uploadVideo(appNumber, userId, videoCode,videoPart,recordTimeStamp )
My postman is like this
{
"name": "DSC Upload Video",
"request": {
"method": "POST",
"header": [],
"body": {
"mode": "formdata",
"formdata": [
{
"key": "AppNumber",
"value": "8181",
"type": "text"
},
{
"key": "UserID",
"value": "d1553a07-0cf0-4d22-a35c-5c38f86a5d30",
"type": "text"
},
{
"key": "VideoCode",
"value": "546",
"type": "text"
},
{
"key": "Video",
"type": "file",
"src": "/C:/Users/Umyha/Downloads/Happy New Year.mp4"
},
{
"key": "RecordTimeStamp",
"value": "1972-11-01 00:00:00",
"type": "text"
}
]
},
"url": {
"raw": "https://uatapi.prodigisign.org/api/ChatBotSNS/dsc-upload-video",
"protocol": "https",
"host": [
"uatapi",
"prodigisign",
"org"
],
"path": [
"api",
"ChatBotSNS",
"dsc-upload-video"
]
}
},
"response": []
}
Can anybody say where I am doing wrong. I have json like that
[
{
"id": "1",
"name": "ff",
"surname": "ggg",
"cap": "10000"
},
{
"id": "1",
"name": "aaa",
"surname": "hhh",
"cap": "22222"
},
{
"id": "1",
"name": "rrr",
"surname": "hhhhhdr",
"cap": "33333"
},
{
"id": "1",
"name": "hhh",
"surname": "qqqqq",
"cap": "44444"
}
]
And I parse to this class.
data class ResponseList(
val capList: List<Response>?
) {
data class Response(
#JsonProperty("id")
val id: String,
#JsonProperty("name")
val name: String,
#JsonProperty("surname")
val surname: String,
#JsonProperty("cap")
val cap: String
)
}
When I try to parse it the list is always null and if I try to test it I have this error:
Cannot deserialize value of type com.myapp.ResponseList from Array value (token JsonToken.START_ARRAY)
just class Response is needed, like following:
fun test(){
val jsonStr = "your json str"
val mapper = ObjectMapper()
val lendReco: List<Response> =
mapper.readValue(jsonStr, object : TypeReference<List<Response?>?>() {})
}
data class Response(
#JsonProperty("id")
val id: String,
#JsonProperty("name")
val name: String,
#JsonProperty("surname")
val surname: String,
#JsonProperty("cap")
val cap: String
)
I've read through multiple posts on StackOverflow, but haven't found a solution that fits my problem yet. Could you please help me fix this Retrofit error?
JSON response:
{
"products": [
{
"barcode_number": "8000040000802",
"barcode_type": "EAN",
"barcode_formats": "EAN 8000040000802",
"mpn": "",
"model": "",
"asin": "",
"product_name": "Campari Bitter 25% Vol. 1 L",
"title": "",
"category": "Food, Beverages & Tobacco > Beverages > Alcoholic Beverages > Bitters",
"manufacturer": "Campari",
"brand": "Campari",
"label": "",
"author": "",
"publisher": "",
"artist": "",
"actor": "",
"director": "",
"studio": "",
"genre": "",
"audience_rating": "",
"ingredients": "",
"nutrition_facts": "",
"color": "",
"format": "",
"package_quantity": "",
"size": "",
"length": "",
"width": "",
"height": "",
"weight": "",
"release_date": "",
"description": "",
"features": [],
"images": [
"https://images.barcodelookup.com/19631/196313718-1.jpg"
],
"stores": [
{
"store_name": "Rakuten Deutschland GmbH",
"store_price": "16.50",
"product_url": "https://www.rakuten.de/produkt/campari-bitter-25-vol-1-l-1826679605",
"currency_code": "EUR",
"currency_symbol": "€"
}
],
"reviews": []
}
]
}
Data classes that have been created by the JSON to Kotlin plugin:
data class BaseResponse(
val products: List<Product>
)
Product:
data class Product(
val actor: String,
val artist: String,
val asin: String,
val audience_rating: String,
...
)
Store:
data class Store(
val currency_code: String,
val currency_symbol: String,
val product_url: String,
val store_name: String,
val store_price: String
)
Service:
interface BarcodeLookupApiService {
#GET("products")
suspend fun getArticleData(#Query("barcode") barcode: String,
#Query("key") key: String): List<BaseResponse>
}
Retrofit Builder:
object RetrofitBuilder {
private const val BASE_URL = "https://api.barcodelookup.com/v2/"
private fun getRetrofit(): Retrofit {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
val apiService: BarcodeLookupApiService =
getRetrofit().create(BarcodeLookupApiService::class.java)
}
Are the data classes created by the plugin not right? Or should my service not return a list? I've tried returning a simple BaseResponse object but that doesn't work either.
Change your interface as shown below:
interface BarcodeLookupApiService {
#GET("products")
suspend fun getArticleData(#Query("barcode") barcode: String,
#Query("key") key: String): BaseResponse
}
and to get list of products do as shown below:
baseRespose.ProductsList
This will fix your issue. The response is an object with has an array inside object. Hence you are getting error.
In my case I was using Laravel framework to build my web service or Rest Api with Sanctum. Ok the problem was here:
{
"result": {
"message": "Registrado correctamente",
"success": true,
"status": 200,
"error": null
}
}
The GsonConverter queries of brackets yes look here be careful:
{
"result": [
{
"message": "Registrado correctamente",
"success": true,
"status": 200,
"error": null
}
]
I update my backend Api:
$result = [
'message' => 'Registrado correctamente',
'success' => true,
'status' => 200,
'error' => null
];
return response()->json([
'result' => $result,
], 200);
to
return response()->json([
'result' => [$result],
], 200);
See careful I have added brackets [ ] to 'result'. This fixed my problem.
My two data class were this:
#Parcelize
data class RegisterResponseObj(
val message: String,
val success: Boolean,
val status: Int = -1,
val error: String?,
) : Parcelable
data class RegisterResponse(val result: List<RegisterResponseObj>)
The web service:
interface WebService {
#FormUrlEncoded
#Headers("Accept: application/json")
#POST("register")
suspend fun registerUser(#Field("name") name: String,
#Field("email") email: String,
#Field("password")password: String): RegisterResponse
}
Cheers!
I'm trying to get page posts attachments. This is a JSON which I try to get:
{
"attachments": {
"data": [
{
"media": {
"image": {
"height": 720,
"src": "url",
"width": 720
}
}
}
]
},
"id": "post_id"
}
My #GET request:
#GET("{post_id}")
fun getPostsAttachments(#Path("post_id") postId : String?,
#Query("access_token") authToken: String?,
#Query("fields") media : String?)
:Observable<AttachmentsList>
Observable:
var getPostsAttachments: Observable<AttachmentsList> = facebook.getPostsAttachments(postId, "app_token", "attachments")
getPostsAttachments.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribeBy(
onNext = { result ->
imgUrl?.addAll(result.data)
Log.d("TAG_NEXT", "$result")
},
onError = { throwable -> Log.d("TAG_ERROR", throwable.toString()) },
onComplete = { Log.d("TAG_COMPLETE", "$imgUrl") }
)
And it return D/TAG_NEXT: AttachmentsList(data=null) and D/TAG_COMPLETE: null.
How can I fix it ? Maybe my link request is wrong ?
From what I can see on https://developers.facebook.com/docs/graph-api/reference/v2.11/attachment your path for the call is wrong. Try changing the Retrofit call annotation to #GET("{post_id}/attachments").
I have a JSON response, which looks like this:
{
"equipment_layer": [
{
"id": 2,
"name": "Gateway",
"detail": "All gateways"
},
{
"id": 3,
"name": "Node",
"detail": "All Nodes"
},
{
"id": 1,
"name": "Miscellaneous",
"detail": "All miscellaneous assets"
},
{
"id": 4,
"name": "Sensors",
"detail": "All Sensors"
},
{
"id": 5,
"name": "IRM",
"detail": "Installation required material"
},
{
"id": 6,
"name": "Communication",
"detail": "All communication devices such as Cellular Router, ETU etc. which are purely communication"
}
],
"data": {
"1": [
{
"equipment_id": 353,
"item_quantity": 1,
"name": "DC Current Transformer (20mm) (Old)",
"shortcode": "SNS-DCI-CT20m-R1A",
"part_number": "718,804,805,",
"equipment_layer_id": 1,
"equipment_layer_name": "Miscellaneous"
},
{
"equipment_id": 357,
"item_quantity": 1,
"name": "Fuel Sensor - B4 (Old)",
"shortcode": "SNS-FUL-PSR-R1A",
"part_number": "718,810,811",
"equipment_layer_id": 1,
"equipment_layer_name": "Miscellaneous"
}
],
"2": [
{
"equipment_id": 345,
"item_quantity": 1,
"name": "RTU (Old)",
"shortcode": "RAN-RTU-PMCL-R1A",
"part_number": "787,788,789",
"equipment_layer_id": 2,
"equipment_layer_name": "Gateway"
}
],
"3": [
{
"equipment_id": 356,
"item_quantity": 1,
"name": "Battery Analyzer (Product) (Old)",
"shortcode": "RAN-BAM-PMCL-R1A",
"part_number": "787,808,809",
"equipment_layer_id": 3,
"equipment_layer_name": "Node"
}
],
"4": [
{
"equipment_id": 346,
"item_quantity": 1,
"name": "DC Current Transformer (30mm) (Old)",
"shortcode": "SNS-CT-DCI-R1A",
"part_number": "718,792,793",
"equipment_layer_id": 4,
"equipment_layer_name": "Sensors"
},
{
"equipment_id": 350,
"item_quantity": 1,
"name": "AC Block CT (Old)",
"shortcode": "SNS-ACI-BLK-R1A",
"part_number": "718,790,791",
"equipment_layer_id": 4,
"equipment_layer_name": "Sensors"
}
]
}
}
Now the part after the "data" label is dynamic, in a response I can have subarrays of "1", "2" but not of "3" or "4".The POJO of the data inside is same as you can see. So how can I parse this data? I'm using Rerofit2 with Gson.converterfactory. I've tried jsonchema2pojo as well but the data inside the "data" object is not showing up.
I've tried to follow this method:
Parsing Retrofit2 result using Gson with different JSON structures but I can't seem to trigger the UnrwapConverter.
This is my converterfactory implementation:
internal class UnwrappingGsonConverterFactory private constructor(private val gson: Gson) : Converter.Factory() {
override fun responseBodyConverter(type: Type, annotations: Array<Annotation>, retrofit: Retrofit): Converter<ResponseBody, *> ?{
if (!needsUnwrapping(annotations)) {
return super.responseBodyConverter(type, annotations, retrofit)
}
val typeAdapter = gson.getAdapter(TypeToken.get(type))
return UnwrappingResponseConverter(typeAdapter)
}
private class UnwrappingResponseConverter (private val typeAdapter: TypeAdapter<*>) : Converter<ResponseBody, Any> , AnkoLogger{
#Throws(IOException::class)
override fun convert(responseBody: ResponseBody): Any? {
responseBody.use { responseBody ->
JsonReader(responseBody.charStream()).use({ jsonReader ->
// Checking if the JSON document current value is null
val token = jsonReader.peek()
if (token === JsonToken.NULL) {
return null
}
// If it's an object, expect `{`
jsonReader.beginObject()
var value: Any? = null
// And iterate over all properties
while (jsonReader.hasNext()) {
val data = jsonReader.nextName()
debug("Unwrap Stuff: $data")
when (data) {
"1", "2", "3", "4", "5", "6" -> value = typeAdapter.read(jsonReader)
else ->jsonReader.skipValue()
}
}
// Consume the object end `}`
jsonReader.endObject()
return value
})
}
}
}
companion object {
fun create(gson: Gson): Converter.Factory {
return UnwrappingGsonConverterFactory(gson)
}
private fun needsUnwrapping(annotations: Array<Annotation>): Boolean {
for (annotation in annotations) {
if (annotation is Unwrap) {
return true
}
}
return false
}
}
}
And the interface:
#Retention(AnnotationRetention.RUNTIME)
#Target(AnnotationTarget.FUNCTION)
annotation class Unwrap
My data classes are these:
data class ActivityNodes(#SerializedName("equipment_layer") val equipmentLayer: List<EquipmentLayer>,
#SerializedName("data") val data: nodeData)
data class nodeData (#SerializedName("1") val nodeList: List<dataItem>) <-- this is where I need someway to tell SerializedName that the value can be anything from 1 to 6
data class dataItem(#SerializedName("equipment_id") val equipmentId: Int,
#SerializedName("item_quantity") val itemQuantity: Int,
#SerializedName("name") val name: String,
#SerializedName("shortcode") val shortCode: String,
#SerializedName("part_number") val partNumber: String,
#SerializedName("equipment_layer_id") val equipmentLayerId: Int,
#SerializedName("equipment_layer_name") val equipmentLayerName: String,
var isScanned: Boolean = false )
data class EquipmentLayer(#SerializedName("id") val id: Int,
#SerializedName("name") val name: String,
#SerializedName("detail") val details: String)
For the dynamic JSON, you have to parse the JSON string manually. To get JSON string from retrofit you have to use ScalarsConverterFactory instead of GsonConverterFactory.
Add this dependency:
compile 'com.squareup.retrofit2:converter-scalars:2.3.0'
Create Adapter like this:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://echo.jsontest.com")
.addConverterFactory(ScalarsConverterFactory.create())
.build()
Create request method with ResponseBody
public interface MyService {
#GET("/key/value/one/two")
Call<ResponseBody> getData();
}
You can get Json String like this:
MyService service = retrofit.create(MyService.class);
Call<ResponseBody> result = service.getData();
result.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Response<ResponseBody> response) {
try {
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Throwable t) {
e.printStackTrace();
}
});
Now you have to parse the JSON string manually to get your data from JSON.
Hope it helps:)
use below for the part of "data" of json:
Type mapType = new TypeToken<Map<String, List<EqupmentDetail.class>>>() {}.getType(); // define generic type
Map<String, List<EqupmentDetail.class>> result= gson.fromJson(new InputStreamReader(source), mapType);
here define EqipmentDetails class same as your refence
this will definitely work