Make subsonic error parser more fail safe.
Now it should parse more malformed error json, though having "code" field is still mandatory. Signed-off-by: Yahor Berdnikau <egorr.berd@gmail.com>
This commit is contained in:
parent
b38f4894c3
commit
0b5cc5d3f3
|
@ -113,6 +113,42 @@ class SubsonicApiErrorsTest : SubsonicAPIClientTest() {
|
||||||
response.assertError(RequestedDataWasNotFound)
|
response.assertError(RequestedDataWasNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Should parse error with reversed tokens order`() {
|
||||||
|
mockWebServerRule.enqueueResponse("reversed_tokens_generic_error.json")
|
||||||
|
|
||||||
|
val response = client.api.ping().execute()
|
||||||
|
|
||||||
|
response.assertError(Generic("Video streaming not supported"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Should parse error if json contains error first before other fields`() {
|
||||||
|
mockWebServerRule.enqueueResponse("error_first_generic_error.json")
|
||||||
|
|
||||||
|
val response = client.api.ping().execute()
|
||||||
|
|
||||||
|
response.assertError(Generic("Video streaming not supported"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Should parse error if json doesn't contain message field`() {
|
||||||
|
mockWebServerRule.enqueueResponse("without_message_generic_error.json")
|
||||||
|
|
||||||
|
val response = client.api.ping().execute()
|
||||||
|
|
||||||
|
response.assertError(Generic(""))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Should parse error if error json contains additional object`() {
|
||||||
|
mockWebServerRule.enqueueResponse("with_additional_json_object_generic_error.json")
|
||||||
|
|
||||||
|
val response = client.api.ping().execute()
|
||||||
|
|
||||||
|
response.assertError(Generic(""))
|
||||||
|
}
|
||||||
|
|
||||||
private fun Response<SubsonicResponse>.assertError(expectedError: SubsonicError) =
|
private fun Response<SubsonicResponse>.assertError(expectedError: SubsonicError) =
|
||||||
with(body()) {
|
with(body()) {
|
||||||
error `should not be` null
|
error `should not be` null
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"subsonic-response": {
|
||||||
|
"error": {
|
||||||
|
"message": "Video streaming not supported",
|
||||||
|
"code": 0
|
||||||
|
},
|
||||||
|
"version": "1.8.0",
|
||||||
|
"status": "failed"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"subsonic-response": {
|
||||||
|
"status": "failed",
|
||||||
|
"version": "1.8.0",
|
||||||
|
"error": {
|
||||||
|
"message": "Video streaming not supported",
|
||||||
|
"code": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"subsonic-response": {
|
||||||
|
"status": "failed",
|
||||||
|
"version": "1.8.0",
|
||||||
|
"error": {
|
||||||
|
"code": 0,
|
||||||
|
"unicorn" : {
|
||||||
|
"code": 41,
|
||||||
|
"message": "Unicorns doesn't exist!"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"subsonic-response": {
|
||||||
|
"status": "failed",
|
||||||
|
"version": "1.8.0",
|
||||||
|
"error": {
|
||||||
|
"code": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
package org.moire.ultrasonic.api.subsonic
|
package org.moire.ultrasonic.api.subsonic
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonParser
|
import com.fasterxml.jackson.core.JsonParser
|
||||||
|
import com.fasterxml.jackson.core.JsonToken.END_OBJECT
|
||||||
|
import com.fasterxml.jackson.core.JsonToken.START_OBJECT
|
||||||
import com.fasterxml.jackson.databind.DeserializationContext
|
import com.fasterxml.jackson.databind.DeserializationContext
|
||||||
import com.fasterxml.jackson.databind.JsonDeserializer
|
import com.fasterxml.jackson.databind.JsonDeserializer
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
|
import com.fasterxml.jackson.databind.annotation.JsonDeserialize
|
||||||
|
@ -36,13 +38,17 @@ sealed class SubsonicError(val code: Int) {
|
||||||
|
|
||||||
class SubsonicErrorDeserializer : JsonDeserializer<SubsonicError>() {
|
class SubsonicErrorDeserializer : JsonDeserializer<SubsonicError>() {
|
||||||
override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): SubsonicError {
|
override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): SubsonicError {
|
||||||
p.nextToken() // { -> "code"
|
var code = -1
|
||||||
p.nextToken() // "code" -> codeValue
|
var message = ""
|
||||||
val code = p.valueAsInt
|
while (p.nextToken() != END_OBJECT) {
|
||||||
p.nextToken() // codeValue -> "message"
|
when {
|
||||||
p.nextToken() // "message" -> messageValue
|
p.currentToken == START_OBJECT -> p.skipChildren()
|
||||||
val message = p.text
|
"code".equals(p.currentName, ignoreCase = true) ->
|
||||||
p.nextToken() // value -> }
|
code = p.nextIntValue(-1)
|
||||||
|
"message".equals(p.currentName, ignoreCase = true) ->
|
||||||
|
message = p.nextTextValue()
|
||||||
|
}
|
||||||
|
}
|
||||||
return getError(code, message)
|
return getError(code, message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue