Il y a une petite confusion il me semble. Json_encode() permet de sérialiser un tableau en une chaine qui est dépliable via json_decode() pour retrouver le tableau initial (sous forme de tableau ou d'objet). Il n'y a aucune raison que json_encode() protège contre les failles XSS, c'est tout simplement pas son rôle.
Si tu as déjà un tableau sérialisé dans ta base de données, il te suffit de faire json_decode(), de récupérer tes données et si tu l'affiches dans en sortie (html par exemple), tu fais un htmlspecialchars() dessus.
A l'encodage, on ne modifie jamais les données parce que si pour une raison ou une autre tu as besoin de ces données dans un autre contexte, tu vas devoir les remodifier pour qu'elles soient facilement exploitables. Donc pour répondre à ta question : la solution est la même que pour toute variable utilisateur en sortie, tu fous un htmlspecialchars() dessus
Si tu as déjà un tableau sérialisé dans ta base de données, il te suffit de faire json_decode(), de récupérer tes données et si tu l'affiches dans en sortie (html par exemple), tu fais un htmlspecialchars() dessus.
A l'encodage, on ne modifie jamais les données parce que si pour une raison ou une autre tu as besoin de ces données dans un autre contexte, tu vas devoir les remodifier pour qu'elles soient facilement exploitables. Donc pour répondre à ta question : la solution est la même que pour toute variable utilisateur en sortie, tu fous un htmlspecialchars() dessus