Ошибка декодирования: сбой, ожидание ОБЪЕКТА с полем с именем `gamegrid`

У меня проблема с моим кодом (ELM/JSON/Python (Flask)), поэтому моя проблема в том,

После получения сообщения Мой сервер пытается отправить ответ в представление ELM через JSON. Консоль моего браузера получает это

0:
currentPlayerId: "0"
firstClickCellId: "-1"
gameOverStatus: "1"
gamegrid: Array(9)
0: {hash: "0", value: "-1"}
1: {hash: "1", value: "-1"}
2: {hash: "2", value: "-1"}
3: {hash: "3", value: "-1"}
4: {hash: "4", value: "-1"}
5: {hash: "5", value: "-1"}
6: {hash: "6", value: "-1"}
7: {hash: "7", value: "-1"}
8: {hash: "8", value: "-1"}
length: 9
__proto__: Array(0)
userToPlayId: "1"
__proto__: Object
length: 1
__proto__: Array(0)

Но у меня есть это сообщение сразу после:

Decode error: Failure "Expecting an OBJECT with a field named `gamegrid`" <internals>

Однако поле gamegrid присутствует в полученном сообщении! Я не могу понять, почему это не может быть расшифровано

Я поставил код, чтобы вы могли видеть, что сделано до

====================КОД============================= ================================

Это часть моей модели

type alias Model =
    { 
      users : List User
    , gameOverView: GameOverView
    }
    
type alias GameOverView = 
  {
     gameGrid: List Cell
     ,userToPlayId: String
     ,gameOverStatus : String
     ,firstClickCellId: String
     , currentPlayerId : String
     
  }
  
type alias Cell = 
    {
     hash: String
    ,value: String
    }

Вот декодер этой части

cellDecoder : Decoder Cell
cellDecoder =
    Decode.map2 Cell
        (Decode.field "hash" Decode.string)
        (Decode.field "value" Decode.string)

listCellDecoder : Decoder (List Cell)
listCellDecoder =
  Decode.list cellDecoder
    
gameOverViewDecoder : Decoder GameOverView
gameOverViewDecoder =
    Decode.map5 GameOverView
        (Decode.field "gamegrid" listCellDecoder)
        (Decode.field "userToPlayId" Decode.string)
        (Decode.field "gameOverStatus" Decode.string)
        (Decode.field "firstClickCellId" Decode.string)
        (Decode.field "currentPlayerId" Decode.string)

Вот декодер JSON

decodeExternalGameOverView : Value -> Msg
decodeExternalGameOverView val =
    case Decode.decodeValue gameOverViewDecoder val of
        Ok gameOverView ->
            GotNewGameOverView gameOverView

        Err err ->
            DecodeError err

subscriptions : Model -> Sub Msg
subscriptions model =
    Sub.batch
        [ userlistPort decodeExternalUserlist,
        gameOverViewlistPort decodeExternalGameOverView,
         receiveData ReceivedDataFromJS]

Вот сервер, отправляющий сообщение (обратите внимание, что он успешно получил предыдущее сообщение)

@app.route('/updategrid/', methods=['POST'])
@flask_login.login_required
def checkPlay():
    print("+++++++++++++++++++++++")
    firsCellClikId = request.json["firstClickedId"]
    secondCellClikId = request.json["secondClickedId"]
    userToPlayId = request.json["userToPlay"]
    currentPlayerId = request.json["currentPlayerId"]
    gameOverStatus = "1"
    
    g = []
    for i in range(9):
      grid = {}
      grid["hash"]  = str(i)
      grid["value"] = request.json[str(i)]
      g.append(grid)
    print("checking play turn")
    print("firstCell = ", firsCellClikId, " SecondCell = ", secondCellClikId)
    print("UserToplay = ", userToPlayId, " UserPlayed = ", currentPlayerId)
    
    if(userToPlayId == "0"):
      userToPlayId = "1"
    else:
      userToPlayId = "0"
    #for x, y in g.items():
    send = {
      "gamegrid": g,
      "userToPlayId": userToPlayId,
      "gameOverStatus": gameOverStatus,
      "firstClickCellId": "-1",
      "currentPlayerId": currentPlayerId
    }
    print(send)
    io.emit('gamegrid', [
      
        send,
      
    ]
  , broadcast=True)
    print("New grid sent")
    
    return "ok", 201

часть HTML-шаблона

<script src="//cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js" integrity="sha256-yr4fRk/GU1ehYJPAs8P4JlTgu0Hdsp4ZKrx8bDEDC3I=" crossorigin="anonymous"></script>
<script type="text/javascript" charset="utf-8">
var socket = io();
var app = Elm.Main.init({ node: document.querySelector('#main-content')});
  
socket.on('gamegrid', function(gamegrid){
  console.log("New GameOverView received:", gamegrid);
  app.ports.gameOverViewlistPort.send(gamegrid);
});

Резюме: проблема осталась следующая: консоль javascript (а точнее декодер elm) не находит поле gamegrid пока оно присутствует и соответствует ожидаемому типу (Cell list)

Ваши предложения приветствуются.

С наилучшими пожеланиями::


person Pavel    schedule 24.06.2020    source источник
comment
Что именно представляет собой ввод json, который вы передаете декодеру? Добавление этого к вопросу облегчает обнаружение вероятной ошибки. Кроме того, если вы считаете, что проблема заключается в ваших декодерах Elm, тогда весь серверный код не имеет значения и просто загромождает пост.   -  person kaskelotti    schedule 24.06.2020


Ответы (1)


Я думаю, что ошибка здесь:

io.emit('gamegrid', [
  
    send,
  
    ]
  , broadcast=True)

потому что вы отправляете словарь/объект send как единственный элемент массива. Вы можете увидеть это в выводе консоли и, похоже, вызывает ошибку, потому что массивы не имеют свойства gamegrid - свойство, которое вы хотите, находится в содержащемся объекте.

Замените [send] просто на send, и это должно сработать.

person Robin Zigmond    schedule 24.06.2020
comment
О, спасибо, это была проблема, я думал, что отправка данных в JSON всегда находится внутри квадратных скобок [ ], я заменил их круглыми скобками ( ), и это сработало. Спасибо. - person Pavel; 24.06.2020