[PM-19627] Move Json extension functions to core module

Move JsonExtensions and related tests to `core` module.

- Moved `decodeFromStringOrNull` and related testing from `app` and `authenticator` modules to `core` module.
- Updated all usages of `decodeFromStringOrNull` in `app` and `authenticator` to the new location in `core`.
- Deleted unused `JsonExtensionsTest` and `JsonExtensions.kt` in `app` and `authenticator`.
- Updated dependencies for core.
This commit is contained in:
Patrick Honkonen
2025-03-27 17:37:45 -04:00
parent 5d5bc25a45
commit 1eced037a4
20 changed files with 19 additions and 91 deletions

View File

@@ -2,6 +2,7 @@ package com.x8bit.bitwarden.data.auth.datasource.disk
import android.content.SharedPreferences import android.content.SharedPreferences
import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
import com.bitwarden.core.data.util.decodeFromStringOrNull
import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountTokensJson import com.x8bit.bitwarden.data.auth.datasource.disk.model.AccountTokensJson
import com.x8bit.bitwarden.data.auth.datasource.disk.model.NewDeviceNoticeDisplayStatus import com.x8bit.bitwarden.data.auth.datasource.disk.model.NewDeviceNoticeDisplayStatus
import com.x8bit.bitwarden.data.auth.datasource.disk.model.NewDeviceNoticeState import com.x8bit.bitwarden.data.auth.datasource.disk.model.NewDeviceNoticeState
@@ -10,7 +11,6 @@ import com.x8bit.bitwarden.data.auth.datasource.disk.model.PendingAuthRequestJso
import com.x8bit.bitwarden.data.auth.datasource.disk.model.UserStateJson import com.x8bit.bitwarden.data.auth.datasource.disk.model.UserStateJson
import com.x8bit.bitwarden.data.platform.datasource.disk.BaseEncryptedDiskSource import com.x8bit.bitwarden.data.platform.datasource.disk.BaseEncryptedDiskSource
import com.x8bit.bitwarden.data.platform.datasource.disk.legacy.LegacySecureStorageMigrator import com.x8bit.bitwarden.data.platform.datasource.disk.legacy.LegacySecureStorageMigrator
import com.x8bit.bitwarden.data.platform.util.decodeFromStringOrNull
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow

View File

@@ -1,8 +1,8 @@
package com.x8bit.bitwarden.data.auth.repository.util package com.x8bit.bitwarden.data.auth.repository.util
import com.bitwarden.core.data.util.decodeFromStringOrNull
import com.x8bit.bitwarden.data.auth.repository.model.Organization import com.x8bit.bitwarden.data.auth.repository.model.Organization
import com.x8bit.bitwarden.data.auth.repository.model.PolicyInformation import com.x8bit.bitwarden.data.auth.repository.model.PolicyInformation
import com.x8bit.bitwarden.data.platform.util.decodeFromStringOrNull
import com.x8bit.bitwarden.data.vault.datasource.network.model.PolicyTypeJson import com.x8bit.bitwarden.data.vault.datasource.network.model.PolicyTypeJson
import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson import com.x8bit.bitwarden.data.vault.datasource.network.model.SyncResponseJson
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json

View File

@@ -1,6 +1,7 @@
package com.x8bit.bitwarden.data.autofill.fido2.manager package com.x8bit.bitwarden.data.autofill.fido2.manager
import androidx.credentials.provider.CallingAppInfo import androidx.credentials.provider.CallingAppInfo
import com.bitwarden.core.data.util.decodeFromStringOrNull
import com.bitwarden.fido.ClientData import com.bitwarden.fido.ClientData
import com.bitwarden.fido.Origin import com.bitwarden.fido.Origin
import com.bitwarden.fido.UnverifiedAssetLink import com.bitwarden.fido.UnverifiedAssetLink
@@ -14,7 +15,6 @@ import com.x8bit.bitwarden.data.autofill.fido2.model.Fido2RegisterCredentialResu
import com.x8bit.bitwarden.data.autofill.fido2.model.Fido2ValidateOriginResult import com.x8bit.bitwarden.data.autofill.fido2.model.Fido2ValidateOriginResult
import com.x8bit.bitwarden.data.autofill.fido2.model.PasskeyAssertionOptions import com.x8bit.bitwarden.data.autofill.fido2.model.PasskeyAssertionOptions
import com.x8bit.bitwarden.data.autofill.fido2.model.PasskeyAttestationOptions import com.x8bit.bitwarden.data.autofill.fido2.model.PasskeyAttestationOptions
import com.x8bit.bitwarden.data.platform.util.decodeFromStringOrNull
import com.x8bit.bitwarden.data.platform.util.getAppOrigin import com.x8bit.bitwarden.data.platform.util.getAppOrigin
import com.x8bit.bitwarden.data.platform.util.getAppSigningSignatureFingerprint import com.x8bit.bitwarden.data.platform.util.getAppSigningSignatureFingerprint
import com.x8bit.bitwarden.data.platform.util.getSignatureFingerprintAsHexString import com.x8bit.bitwarden.data.platform.util.getSignatureFingerprintAsHexString

View File

@@ -2,8 +2,8 @@ package com.x8bit.bitwarden.data.platform.datasource.disk
import android.content.SharedPreferences import android.content.SharedPreferences
import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
import com.bitwarden.core.data.util.decodeFromStringOrNull
import com.x8bit.bitwarden.data.platform.datasource.disk.model.ServerConfig import com.x8bit.bitwarden.data.platform.datasource.disk.model.ServerConfig
import com.x8bit.bitwarden.data.platform.util.decodeFromStringOrNull
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.onSubscription import kotlinx.coroutines.flow.onSubscription
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json

View File

@@ -2,8 +2,8 @@ package com.x8bit.bitwarden.data.platform.datasource.disk
import android.content.SharedPreferences import android.content.SharedPreferences
import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
import com.bitwarden.core.data.util.decodeFromStringOrNull
import com.x8bit.bitwarden.data.auth.datasource.disk.model.EnvironmentUrlDataJson import com.x8bit.bitwarden.data.auth.datasource.disk.model.EnvironmentUrlDataJson
import com.x8bit.bitwarden.data.platform.util.decodeFromStringOrNull
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.onSubscription import kotlinx.coroutines.flow.onSubscription
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json

View File

@@ -2,10 +2,10 @@ package com.x8bit.bitwarden.data.platform.datasource.disk
import android.content.SharedPreferences import android.content.SharedPreferences
import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
import com.bitwarden.core.data.util.decodeFromStringOrNull
import com.x8bit.bitwarden.data.platform.manager.model.AppResumeScreenData import com.x8bit.bitwarden.data.platform.manager.model.AppResumeScreenData
import com.x8bit.bitwarden.data.platform.repository.model.UriMatchType import com.x8bit.bitwarden.data.platform.repository.model.UriMatchType
import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeoutAction import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeoutAction
import com.x8bit.bitwarden.data.platform.util.decodeFromStringOrNull
import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppLanguage import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppLanguage
import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow

View File

@@ -1,7 +1,7 @@
package com.x8bit.bitwarden.data.platform.datasource.network.util package com.x8bit.bitwarden.data.platform.datasource.network.util
import com.bitwarden.core.data.util.decodeFromStringOrNull
import com.x8bit.bitwarden.data.platform.datasource.network.model.BitwardenError import com.x8bit.bitwarden.data.platform.datasource.network.model.BitwardenError
import com.x8bit.bitwarden.data.platform.util.decodeFromStringOrNull
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import retrofit2.HttpException import retrofit2.HttpException

View File

@@ -1,6 +1,7 @@
package com.x8bit.bitwarden.data.platform.manager package com.x8bit.bitwarden.data.platform.manager
import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
import com.bitwarden.core.data.util.decodeFromStringOrNull
import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource import com.x8bit.bitwarden.data.auth.datasource.disk.AuthDiskSource
import com.x8bit.bitwarden.data.auth.repository.util.activeUserIdChangesFlow import com.x8bit.bitwarden.data.auth.repository.util.activeUserIdChangesFlow
import com.x8bit.bitwarden.data.platform.datasource.disk.PushDiskSource import com.x8bit.bitwarden.data.platform.datasource.disk.PushDiskSource
@@ -18,7 +19,6 @@ import com.x8bit.bitwarden.data.platform.manager.model.SyncFolderDeleteData
import com.x8bit.bitwarden.data.platform.manager.model.SyncFolderUpsertData import com.x8bit.bitwarden.data.platform.manager.model.SyncFolderUpsertData
import com.x8bit.bitwarden.data.platform.manager.model.SyncSendDeleteData import com.x8bit.bitwarden.data.platform.manager.model.SyncSendDeleteData
import com.x8bit.bitwarden.data.platform.manager.model.SyncSendUpsertData import com.x8bit.bitwarden.data.platform.manager.model.SyncSendUpsertData
import com.x8bit.bitwarden.data.platform.util.decodeFromStringOrNull
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.asSharedFlow

View File

@@ -1,8 +1,8 @@
package com.x8bit.bitwarden.data.tools.generator.datasource.disk package com.x8bit.bitwarden.data.tools.generator.datasource.disk
import android.content.SharedPreferences import android.content.SharedPreferences
import com.bitwarden.core.data.util.decodeFromStringOrNull
import com.x8bit.bitwarden.data.platform.datasource.disk.BaseDiskSource import com.x8bit.bitwarden.data.platform.datasource.disk.BaseDiskSource
import com.x8bit.bitwarden.data.platform.util.decodeFromStringOrNull
import com.x8bit.bitwarden.data.tools.generator.repository.model.PasscodeGenerationOptions import com.x8bit.bitwarden.data.tools.generator.repository.model.PasscodeGenerationOptions
import com.x8bit.bitwarden.data.tools.generator.repository.model.UsernameGenerationOptions import com.x8bit.bitwarden.data.tools.generator.repository.model.UsernameGenerationOptions
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json

View File

@@ -1,8 +1,8 @@
package com.x8bit.bitwarden.data.vault.datasource.disk package com.x8bit.bitwarden.data.vault.datasource.disk
import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
import com.bitwarden.core.data.util.decodeFromStringWithErrorCallback
import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager import com.x8bit.bitwarden.data.platform.manager.dispatcher.DispatcherManager
import com.x8bit.bitwarden.data.platform.util.decodeFromStringWithErrorCallback
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.CiphersDao import com.x8bit.bitwarden.data.vault.datasource.disk.dao.CiphersDao
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.CollectionsDao import com.x8bit.bitwarden.data.vault.datasource.disk.dao.CollectionsDao
import com.x8bit.bitwarden.data.vault.datasource.disk.dao.DomainsDao import com.x8bit.bitwarden.data.vault.datasource.disk.dao.DomainsDao

View File

@@ -4,6 +4,7 @@ import android.content.pm.Signature
import android.content.pm.SigningInfo import android.content.pm.SigningInfo
import android.util.Base64 import android.util.Base64
import com.bitwarden.core.data.util.asSuccess import com.bitwarden.core.data.util.asSuccess
import com.bitwarden.core.data.util.decodeFromStringOrNull
import com.bitwarden.fido.ClientData import com.bitwarden.fido.ClientData
import com.bitwarden.fido.Origin import com.bitwarden.fido.Origin
import com.bitwarden.fido.PublicKeyCredentialAuthenticatorAssertionResponse import com.bitwarden.fido.PublicKeyCredentialAuthenticatorAssertionResponse
@@ -19,7 +20,6 @@ import com.x8bit.bitwarden.data.autofill.fido2.model.Fido2ValidateOriginResult
import com.x8bit.bitwarden.data.autofill.fido2.model.PasskeyAssertionOptions import com.x8bit.bitwarden.data.autofill.fido2.model.PasskeyAssertionOptions
import com.x8bit.bitwarden.data.autofill.fido2.model.PasskeyAttestationOptions import com.x8bit.bitwarden.data.autofill.fido2.model.PasskeyAttestationOptions
import com.x8bit.bitwarden.data.autofill.fido2.model.createMockFido2CreateCredentialRequest import com.x8bit.bitwarden.data.autofill.fido2.model.createMockFido2CreateCredentialRequest
import com.x8bit.bitwarden.data.platform.util.decodeFromStringOrNull
import com.x8bit.bitwarden.data.vault.datasource.sdk.VaultSdkSource import com.x8bit.bitwarden.data.vault.datasource.sdk.VaultSdkSource
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.AuthenticateFido2CredentialRequest import com.x8bit.bitwarden.data.vault.datasource.sdk.model.AuthenticateFido2CredentialRequest
import com.x8bit.bitwarden.data.vault.datasource.sdk.model.RegisterFido2CredentialRequest import com.x8bit.bitwarden.data.vault.datasource.sdk.model.RegisterFido2CredentialRequest

View File

@@ -2,13 +2,13 @@ package com.x8bit.bitwarden.data.platform.datasource.disk
import androidx.core.content.edit import androidx.core.content.edit
import app.cash.turbine.test import app.cash.turbine.test
import com.bitwarden.core.data.util.decodeFromStringOrNull
import com.x8bit.bitwarden.data.platform.base.FakeSharedPreferences import com.x8bit.bitwarden.data.platform.base.FakeSharedPreferences
import com.x8bit.bitwarden.data.platform.datasource.network.di.PlatformNetworkModule import com.x8bit.bitwarden.data.platform.datasource.network.di.PlatformNetworkModule
import com.x8bit.bitwarden.data.platform.manager.model.AppResumeScreenData import com.x8bit.bitwarden.data.platform.manager.model.AppResumeScreenData
import com.x8bit.bitwarden.data.platform.repository.model.ClearClipboardFrequency import com.x8bit.bitwarden.data.platform.repository.model.ClearClipboardFrequency
import com.x8bit.bitwarden.data.platform.repository.model.UriMatchType import com.x8bit.bitwarden.data.platform.repository.model.UriMatchType
import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeoutAction import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeoutAction
import com.x8bit.bitwarden.data.platform.util.decodeFromStringOrNull
import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppLanguage import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppLanguage
import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest

View File

@@ -1,11 +1,11 @@
package com.x8bit.bitwarden.data.platform.datasource.disk.util package com.x8bit.bitwarden.data.platform.datasource.disk.util
import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
import com.bitwarden.core.data.util.decodeFromStringOrNull
import com.x8bit.bitwarden.data.platform.datasource.disk.SettingsDiskSource import com.x8bit.bitwarden.data.platform.datasource.disk.SettingsDiskSource
import com.x8bit.bitwarden.data.platform.manager.model.AppResumeScreenData import com.x8bit.bitwarden.data.platform.manager.model.AppResumeScreenData
import com.x8bit.bitwarden.data.platform.repository.model.UriMatchType import com.x8bit.bitwarden.data.platform.repository.model.UriMatchType
import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeoutAction import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeoutAction
import com.x8bit.bitwarden.data.platform.util.decodeFromStringOrNull
import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppLanguage import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppLanguage
import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow

View File

@@ -3,8 +3,8 @@ package com.bitwarden.authenticator.data.platform.datasource.disk
import android.content.SharedPreferences import android.content.SharedPreferences
import com.bitwarden.authenticator.data.platform.datasource.disk.BaseDiskSource.Companion.BASE_KEY import com.bitwarden.authenticator.data.platform.datasource.disk.BaseDiskSource.Companion.BASE_KEY
import com.bitwarden.authenticator.data.platform.datasource.disk.model.ServerConfig import com.bitwarden.authenticator.data.platform.datasource.disk.model.ServerConfig
import com.bitwarden.authenticator.data.platform.util.decodeFromStringOrNull
import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
import com.bitwarden.core.data.util.decodeFromStringOrNull
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.onSubscription import kotlinx.coroutines.flow.onSubscription
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json

View File

@@ -3,8 +3,8 @@ package com.bitwarden.authenticator.data.platform.datasource.disk
import android.content.SharedPreferences import android.content.SharedPreferences
import com.bitwarden.authenticator.data.platform.datasource.disk.BaseDiskSource.Companion.BASE_KEY import com.bitwarden.authenticator.data.platform.datasource.disk.BaseDiskSource.Companion.BASE_KEY
import com.bitwarden.authenticator.data.platform.datasource.disk.model.FeatureFlagsConfiguration import com.bitwarden.authenticator.data.platform.datasource.disk.model.FeatureFlagsConfiguration
import com.bitwarden.authenticator.data.platform.util.decodeFromStringOrNull
import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
import com.bitwarden.core.data.util.decodeFromStringOrNull
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.onSubscription import kotlinx.coroutines.flow.onSubscription
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json

View File

@@ -1,19 +0,0 @@
package com.bitwarden.authenticator.data.platform.util
import kotlinx.serialization.SerializationException
import kotlinx.serialization.json.Json
/**
* Attempts to decode the given JSON [string] into the given type [T]. If there is an error in
* processing the JSON or deserializing it to an instance of [T], `null` will be returned.
*/
inline fun <reified T> Json.decodeFromStringOrNull(
string: String,
): T? =
try {
decodeFromString(string = string)
} catch (e: SerializationException) {
null
} catch (e: IllegalArgumentException) {
null
}

View File

@@ -1,55 +0,0 @@
package com.bitwarden.authenticator.data.platform.util
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertNull
import org.junit.jupiter.api.Test
class JsonExtensionsTest {
private val json = Json
@Test
fun `decodeFromStringOrNull for invalid JSON should return null`() {
assertNull(
json.decodeFromStringOrNull<TestData>(
"""
{]
""",
),
)
}
@Test
fun `decodeFromStringOrNull for valid JSON but an incorrect model should return null`() {
assertNull(
json.decodeFromStringOrNull<TestData>(
"""
{}
""",
),
)
}
@Test
fun `decodeFromStringOrNull for valid JSON and a correct model should parse correctly`() {
assertEquals(
TestData(
data = "test",
),
json.decodeFromStringOrNull<TestData>(
"""
{
"data": "test"
}
""",
),
)
}
}
@Serializable
private data class TestData(
@SerialName("data") val data: String,
)

View File

@@ -1,6 +1,7 @@
plugins { plugins {
alias(libs.plugins.android.library) alias(libs.plugins.android.library)
alias(libs.plugins.kotlin.android) alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.serialization)
} }
android { android {
@@ -36,6 +37,7 @@ android {
dependencies { dependencies {
implementation(libs.kotlinx.coroutines.android) implementation(libs.kotlinx.coroutines.android)
implementation(libs.kotlinx.serialization)
testImplementation(platform(libs.junit.bom)) testImplementation(platform(libs.junit.bom))
testRuntimeOnly(libs.junit.platform.launcher) testRuntimeOnly(libs.junit.platform.launcher)

View File

@@ -1,4 +1,4 @@
package com.x8bit.bitwarden.data.platform.util package com.bitwarden.core.data.util
import kotlinx.serialization.SerializationException import kotlinx.serialization.SerializationException
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json

View File

@@ -1,4 +1,4 @@
package com.x8bit.bitwarden.data.platform.util package com.bitwarden.core.data.util
import kotlinx.serialization.SerialName import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable