0

I am coding a chess online game, but the problem is that json won't send an array of classes...(Each class is a type of a piece)

How do I send the board(2-dimensional lists filled with "None"'s and objects) through sockets to the client?

import os
from pawn import Pawn
from rook import Rook
from queen import Queen
from bishop import Bishop
from king import King
from knight import Knight
from playsound import playsound
import socket
import json

LISTEN_PORT = 46

def send_to_serv(sock, msg):
    sock.sendall(json.dumps(msg).encode())

def recv_from_serv(sock):
    return json.loads(sock.recv(1024).decode())


board = [0] * 8

for i in range(8):
    board[i] = [None] * 8  # initiating board

for i in range(8):  # initiating pawns
    board[6][i] = Pawn('white')
    board[1][i] = Pawn('black')

board[0][0] = Rook('black')
board[0][7] = Rook('black')
board[0][1] = Knight('black')
board[0][6] = Knight('black')
board[0][2] = Bishop('black')
board[0][5] = Bishop('black')
board[0][3] = Queen('black')
board[0][4] = King('black')

board[7][0] = Rook('white')
board[7][7] = Rook('white')
board[7][1] = Knight('white')
board[7][6] = Knight('white')
board[7][2] = Bishop('white')
board[7][5] = Bishop('white')
board[7][3] = Queen('white')
board[7][4] = King('white')

listening_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('127.0.0.1', LISTEN_PORT)
listening_sock.bind(server_address)
listening_sock.listen(1)
client_soc, client_address = listening_sock.accept()

while (True):
    client_msg = recv_from_serv(client_soc)
    msg = board
    send_to_serv(client_soc, msg)

and the error I get is this:

raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type Rook is not JSON serializable
shoham
  • 1
  • 2

1 Answers1

1

There are a couple of ways to work around this. One is to use pickle which has the same interface as JSON but supports (almost) any Python object.

Careful how you use this as pickle essentially allows executing arbitrary code that is passed to it so only do this for trusted connections. If this socket were open to the internet anyone with knowledge of it would be able to execute arbitrary code on your server.

First, we import it. If in Python 2 you'll want to import cPickle because it's faster - in Python 3 importing pickle defaults to cPickle if available:

# python 3
import pickle

#python 2
import cPickle as pickle

then we can use it to send the data:

def send_to_serv(sock, msg):
    sock.sendall(pickle.dumps(msg))

def recv_from_serv(sock):
    return pickle.loads(sock.recv(1024).decode())

An alternative options would be to deconstruct the classes into dictionaries. It's a little more complex but will allow sharing the information with non-Python interfaces. Without the class definitions, though, I can't give a sample for that.

Michoel
  • 834
  • 5
  • 16
  • It might be worth noting that opening an unauthenticated socket for reading pickle effectively opens a machine for arbitrary code execution by anyone. – MisterMiyagi Oct 28 '20 at 14:34