use custom JsonAdapter to be compatible with instances that have a custom subscribing feature (#2298)
This commit is contained in:
		
					parent
					
						
							
								1586817c3d
							
						
					
				
			
			
				commit
				
					
						2fd01f7e2d
					
				
			
		
					 3 changed files with 170 additions and 1 deletions
				
			
		|  | @ -15,7 +15,9 @@ | |||
| 
 | ||||
| package com.keylesspalace.tusky.entity | ||||
| 
 | ||||
| import com.google.gson.annotations.JsonAdapter | ||||
| import com.google.gson.annotations.SerializedName | ||||
| import com.keylesspalace.tusky.json.GuardedBooleanAdapter | ||||
| 
 | ||||
| data class Relationship( | ||||
|     val id: String, | ||||
|  | @ -26,7 +28,11 @@ data class Relationship( | |||
|     @SerializedName("muting_notifications") val mutingNotifications: Boolean, | ||||
|     val requested: Boolean, | ||||
|     @SerializedName("showing_reblogs") val showingReblogs: Boolean, | ||||
|     val subscribing: Boolean? = null, // Pleroma extension | ||||
|     /* Pleroma extension, same as 'notifying' on Mastodon. | ||||
|      * Some instances like qoto.org have a custom subscription feature where 'subscribing' is a json object, | ||||
|      * so we use the custom GuardedBooleanAdapter to ignore the field if it is not a boolean. | ||||
|      */ | ||||
|     @JsonAdapter(GuardedBooleanAdapter::class) val subscribing: Boolean? = null, | ||||
|     @SerializedName("domain_blocking") val blockingDomain: Boolean, | ||||
|     val note: String?, // nullable for backward compatibility / feature detection | ||||
|     val notifying: Boolean? // since 3.3.0rc | ||||
|  |  | |||
|  | @ -0,0 +1,33 @@ | |||
| /* Copyright 2022 Tusky Contributors | ||||
|  * | ||||
|  * This file is a part of Tusky. | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify it under the terms of the | ||||
|  * GNU General Public License as published by the Free Software Foundation; either version 3 of the | ||||
|  * License, or (at your option) any later version. | ||||
|  * | ||||
|  * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even | ||||
|  * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General | ||||
|  * Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License along with Tusky; if not, | ||||
|  * see <http://www.gnu.org/licenses>. */ | ||||
| 
 | ||||
| package com.keylesspalace.tusky.json | ||||
| 
 | ||||
| import com.google.gson.JsonDeserializationContext | ||||
| import com.google.gson.JsonDeserializer | ||||
| import com.google.gson.JsonElement | ||||
| import com.google.gson.JsonParseException | ||||
| import java.lang.reflect.Type | ||||
| 
 | ||||
| class GuardedBooleanAdapter : JsonDeserializer<Boolean?> { | ||||
|     @Throws(JsonParseException::class) | ||||
|     override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): Boolean? { | ||||
|         return if (json.isJsonObject) { | ||||
|             null | ||||
|         } else { | ||||
|             json.asBoolean | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | @ -0,0 +1,130 @@ | |||
| package com.keylesspalace.tusky.json | ||||
| 
 | ||||
| import com.google.gson.Gson | ||||
| import com.keylesspalace.tusky.entity.Relationship | ||||
| import org.junit.Assert.assertEquals | ||||
| import org.junit.Test | ||||
| 
 | ||||
| class GuardedBooleanAdapterTest { | ||||
| 
 | ||||
|     private val gson = Gson() | ||||
| 
 | ||||
|     @Test | ||||
|     fun `should deserialize Relationship when attribute 'subscribing' is a boolean`() { | ||||
|         val jsonInput = """ | ||||
|             { | ||||
|               "id": "1", | ||||
|               "following": true, | ||||
|               "showing_reblogs": true, | ||||
|               "notifying": false, | ||||
|               "followed_by": true, | ||||
|               "blocking": false, | ||||
|               "blocked_by": false, | ||||
|               "muting": false, | ||||
|               "muting_notifications": false, | ||||
|               "requested": false, | ||||
|               "domain_blocking": false, | ||||
|               "endorsed": false, | ||||
|               "note": "Hi", | ||||
|               "subscribing": true | ||||
|             } | ||||
|         """.trimIndent() | ||||
| 
 | ||||
|         assertEquals( | ||||
|             Relationship( | ||||
|                 id = "1", | ||||
|                 following = true, | ||||
|                 followedBy = true, | ||||
|                 blocking = false, | ||||
|                 muting = false, | ||||
|                 mutingNotifications = false, | ||||
|                 requested = false, | ||||
|                 showingReblogs = true, | ||||
|                 subscribing = true, | ||||
|                 blockingDomain = false, | ||||
|                 note = "Hi", | ||||
|                 notifying = false | ||||
|             ), | ||||
|             gson.fromJson(jsonInput, Relationship::class.java) | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     fun `should deserialize Relationship when attribute 'subscribing' is an object`() { | ||||
|         val jsonInput = """ | ||||
|             { | ||||
|               "id": "2", | ||||
|               "following": true, | ||||
|               "showing_reblogs": true, | ||||
|               "notifying": false, | ||||
|               "followed_by": true, | ||||
|               "blocking": false, | ||||
|               "blocked_by": false, | ||||
|               "muting": false, | ||||
|               "muting_notifications": false, | ||||
|               "requested": false, | ||||
|               "domain_blocking": false, | ||||
|               "endorsed": false, | ||||
|               "note": "Hi", | ||||
|               "subscribing": { } | ||||
|             } | ||||
|         """.trimIndent() | ||||
| 
 | ||||
|         assertEquals( | ||||
|             Relationship( | ||||
|                 id = "2", | ||||
|                 following = true, | ||||
|                 followedBy = true, | ||||
|                 blocking = false, | ||||
|                 muting = false, | ||||
|                 mutingNotifications = false, | ||||
|                 requested = false, | ||||
|                 showingReblogs = true, | ||||
|                 subscribing = null, | ||||
|                 blockingDomain = false, | ||||
|                 note = "Hi", | ||||
|                 notifying = false | ||||
|             ), | ||||
|             gson.fromJson(jsonInput, Relationship::class.java) | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     @Test | ||||
|     fun `should deserialize Relationship when attribute 'subscribing' does not exist`() { | ||||
|         val jsonInput = """ | ||||
|             { | ||||
|               "id": "3", | ||||
|               "following": true, | ||||
|               "showing_reblogs": true, | ||||
|               "notifying": false, | ||||
|               "followed_by": true, | ||||
|               "blocking": false, | ||||
|               "blocked_by": false, | ||||
|               "muting": false, | ||||
|               "muting_notifications": false, | ||||
|               "requested": false, | ||||
|               "domain_blocking": false, | ||||
|               "endorsed": false, | ||||
|               "note": "Hi" | ||||
|             } | ||||
|         """.trimIndent() | ||||
| 
 | ||||
|         assertEquals( | ||||
|             Relationship( | ||||
|                 id = "3", | ||||
|                 following = true, | ||||
|                 followedBy = true, | ||||
|                 blocking = false, | ||||
|                 muting = false, | ||||
|                 mutingNotifications = false, | ||||
|                 requested = false, | ||||
|                 showingReblogs = true, | ||||
|                 subscribing = null, | ||||
|                 blockingDomain = false, | ||||
|                 note = "Hi", | ||||
|                 notifying = false | ||||
|             ), | ||||
|             gson.fromJson(jsonInput, Relationship::class.java) | ||||
|         ) | ||||
|     } | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue