Kryonet handles marshaling. The hard bit is what to send and when.
Using a lib like kryonet is recommended and removes the UDP/TCP argument since the lib will make that decision for you. If not always start with TCP, if it really is a bad fit then you can change later. TCP gives you a lot out of the box (flow control, ordering, handshakes and of course resends with packet loss), and UDP is not faster as so many claim. See below for the only exception IMO to this rule.
The type of game strongly dictates architecture. ie Server client, or p2p, turn based. These days everyone is moving to Server client, even for RTS games, so not a bad place to start.
Now the what and when. Lets hope your game is small. That is the entire game state can fit in a single packet, ie about 1500bytes or less. Then every game tick the server sends the entire game state. clients send “actions” when they happen. The server constantly listens to client actions, then updates the state, and at a fix interval sends the entire state to every client. This system does in fact work well with UDP and is the only case i would recomend people use UDP. Flow control and resends are handled implicitly by the server sending a fresh update at whatever rate you deem fit (10 per sec?). Clients always ignore “older” packets. Quake/unreal uses this system. this also works really well with TCP and large states with turned based games. Think old Civ.
If you can’t fit the entire state in a single packet. Then more incremental updates with sync needs to be considered and it a bit harder to do. This is where TCP shines. I don’t need a billion special cases with unrecived packets or out of order packets. But exactly what to send when is much harder to deiced. there are many ways to skin this cat. More details are required.
But no matter what i would start small. Proper small. like a cut down version of the game or something.