问题描述
我有一个Elm解码器并对其进行了测试。测试通过了,但是当我在应用程序上使用解码器时,出现了一个奇怪的错误,该错误似乎与传递的数据不一致。我不知道怎么了。为了公开起见,我是Elm的新手,这是我的第一个应用程序,针对生产。
解码器
type alias ProviderData =
{ uid : String,displayName : Maybe String,photoURL : Maybe String,email : String,phoneNumber : Maybe String,providerId : String
}
type alias TokenManager =
{ apiKey : String,refreshToken : String,accessToken : String,expirationTime : Time.Posix
}
type alias User =
{ uid : String,emailVerified : Bool,isAnonymous : Bool,tenantId : Maybe String,providerData : List ProviderData,apiKey : String,appName : String,authDomain : String,stsTokenManager : TokenManager,redirectEventId : Maybe String,lastLoginAt : Time.Posix,createdAt : Time.Posix
}
type alias Model =
{ isUserSignedIn : Bool,isWaitingForSignInLink : Bool,user : Maybe User
}
unauthenticatedUser : Model
unauthenticatedUser =
{ isUserSignedIn = False,isWaitingForSignInLink = False,user = Nothing
}
decoder : Json.Value -> Model
decoder json =
case Json.decodeValue authDecoder (Debug.log ("Decoding " ++ Json.Encode.encode 4 json) json) of
Ok model ->
model
Err err ->
Debug.log (Debug.toString err) unauthenticatedUser
authDecoder : Json.Decoder Model
authDecoder =
Json.succeed Model
|> required "isUserSignedIn" Json.bool
|> required "isWaitingForSignInLink" Json.bool
|> optional "user" (Json.map Just decodeUser) Nothing
decodeUser : Json.Decoder User
decodeUser =
Json.succeed User
|> required "uid" Json.string
|> optional "displayName" (Json.map Just Json.string) Nothing
|> optional "photoURL" (Json.map Just Json.string) Nothing
|> required "email" Json.string
|> required "emailVerified" Json.bool
|> optional "phoneNumber" (Json.map Just Json.string) Nothing
|> required "isAnonymous" Json.bool
|> optional "tenantId" (Json.map Just Json.string) Nothing
|> required "providerData" (Json.list decodeProviderData)
|> required "apiKey" Json.string
|> required "appName" Json.string
|> required "authDomain" Json.string
|> required "stsTokenManager" decodeTokenManager
|> optional "redirectEventId" (Json.map Just Json.string) Nothing
|> required "lastLoginAt" timestampFromString
|> required "createdAt" timestampFromString
decodeProviderData : Json.Decoder ProviderData
decodeProviderData =
Json.succeed ProviderData
|> required "uid" Json.string
|> optional "displayName" (Json.map Just Json.string) Nothing
|> optional "photoURL" (Json.map Just Json.string) Nothing
|> required "email" Json.string
|> optional "phoneNumber" (Json.map Just Json.string) Nothing
|> required "providerId" Json.string
decodeTokenManager : Json.Decoder TokenManager
decodeTokenManager =
Json.succeed TokenManager
|> required "apiKey" Json.string
|> required "refreshToken" Json.string
|> required "accessToken" Json.string
|> required "expirationTime" timestampFromInt
timestampFromString : Json.Decoder Time.Posix
timestampFromString =
Json.andThen
(\str ->
case String.toInt str of
Just ts ->
Json.succeed (Time.millisToPosix ts)
Nothing ->
Json.fail (str ++ " is not a timetamp")
)
Json.string
timestampFromInt : Json.Decoder Time.Posix
timestampFromInt =
Json.andThen
(\ts ->
Json.succeed (Time.millisToPosix ts)
)
Json.int
unauthenticatedUser : Model
unauthenticatedUser =
{ isUserSignedIn = False,user = Nothing
}
错误
Failure "Json.Decode.oneOf failed in the following 2 ways:
(1) Problem with the given value:
{
"uid": "","displayName": null,"photoURL": null,"email": "[email protected]","emailVerified": true,"phoneNumber": null,"isAnonymous": false,"tenantId": null,"providerData": [
{
"uid": "[email protected]","providerId": "password"
}
],"apiKey": "","appName": "[DEFAULT]","authDomain": "example.firebaseapp.com","stsTokenManager": {
"apiKey": "","refreshToken": "","accessToken": "","expirationTime": 1603998440000
},"redirectEventId": null,"lastLoginAt": "1603576515267","createdAt": "1603573117442","multiFactor": {
"enrolledFactors": []
}
}
Expecting an OBJECT with a field named `createdAt`
(2) Problem with the given value:
{
"uid": "","multiFactor": {
"enrolledFactors": []
}
}
Expecting null" <internals>: { isUserSignedIn = False,user = Nothing }
测试
module Tests exposing (..)
import Expect
import Json.Decode as Json
import Modules.Firebase as Firebase
import Test exposing (..)
import Time
all : Test
all =
describe "Test Firebase"
[ test "Test auth JSON" <|
\_ ->
let
input =
"""
{
"isUserSignedIn": true,"isWaitingForSignInLink": false,"user": {
"uid": "xxxxxxxxxxxx","providerData": [
{
"uid": "[email protected]","providerId": "password"
}
],"apiKey": "apikey.xxxxxxxxx","authDomain": "example.com","stsTokenManager": {
"apiKey": "apikey.xxxxxxxxx","refreshToken": "refresh.xxxxxxxxxxxx","accessToken": "access.xxxxxxxxxxxx","expirationTime": 1603825391000
},"multiFactor": {
"enrolledFactors": []
}
}
}
"""
decodedOutput =
case Json.decodeString Json.value input of
Ok value ->
Ok (Firebase.decoder value)
Err err ->
Err err
in
Expect.equal decodedOutput
(Ok firebaseModel)
]
firebaseModel : Firebase.Model
firebaseModel =
{ isUserSignedIn = True,user =
Just
{ uid = "xxxxxxxxxxxx",displayName = Nothing,photoURL = Nothing,email = "[email protected]",emailVerified = True,phoneNumber = Nothing,isAnonymous = False,tenantId = Nothing,providerData =
[ { uid = "[email protected]",providerId = "password"
}
],apiKey = "apikey.xxxxxxxxx",appName = "[DEFAULT]",authDomain = "example.com",stsTokenManager =
{ apiKey = "apikey.xxxxxxxxx",refreshToken = "refresh.xxxxxxxxxxxx",accessToken = "access.xxxxxxxxxxxx",expirationTime = Time.millisToPosix 1603825391000
},redirectEventId = Nothing,lastLoginAt = Time.millisToPosix 1603576515267,createdAt = Time.millisToPosix 1603573117442
}
}
于2020-10-30编辑
调试信息
尝试调试此问题,我开始逐字段逐步构建模型,以了解问题所在。以下模型和解码器可以正常工作:
...
type alias User =
{ uid : String,providerData : List ProviderData
}
...
decodeUser : Json.Decoder User
decodeUser =
Json.succeed User
|> required "uid" Json.string
|> optional "displayName" (Json.nullable Json.string) Nothing
|> optional "photoURL" (Json.nullable Json.string) Nothing
|> required "email" Json.string
|> required "emailVerified" Json.bool
|> optional "phoneNumber" (Json.nullable Json.string) Nothing
|> required "isAnonymous" Json.bool
|> optional "tenantId" (Json.nullable Json.string) Nothing
|> required "providerData" (Json.list decodeProviderData)
...
注1-所有其他代码保持不变。
注2-输入数据保持不变。
注释3-我通过@ 5ndG建议将Json.map Just
更改为Json.nullable
。我也尝试过optional "field" (Json.nullable Json.string) Nothing
至required "field" (Json.nullable Json.string)
,但问题仍然存在。
进行此更改后,模型将达到预期状态,减去我删除的字段。通过添加下一个字段|> required "apiKey" Json.string
,它会因相同的问题而开始失败。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)