Подтвердить что ты не робот

Сериализация и десериализация Json и Json Array в Unity

У меня есть список элементов, отправленных из файла PHP в Unity с помощью WWW.

WWW.text выглядит так:

[
    {
        "playerId": "1",
        "playerLoc": "Powai"
    },
    {
        "playerId": "2",
        "playerLoc": "Andheri"
    },
    {
        "playerId": "3",
        "playerLoc": "Churchgate"
    }
]

Где я обрежу лишние [] из string. Когда я пытаюсь разобрать его с помощью Boomlagoon.JSON, Boomlagoon.JSON только первый объект. Я обнаружил, что я должен deserialize() список и импортировал MiniJSON.

Но я запутался, как deserialize() этот список. Я хочу пройтись по каждому объекту JSON и получить данные. Как я могу сделать это в Unity с помощью С#?

Я использую класс

public class player
{
    public string playerId { get; set; }
    public string playerLoc { get; set; }
    public string playerNick { get; set; }
}

После обрезки [] я могу проанализировать JSON с помощью MiniJSON. Но он возвращает только первый KeyValuePair.

IDictionary<string, object> players = Json.Deserialize(serviceData) as IDictionary<string, object>;

foreach (KeyValuePair<string, object> kvp in players)
{
    Debug.Log(string.Format("Key = {0}, Value = {1}", kvp.Key, kvp.Value));
}

Спасибо!

4b9b3361

Ответ 1

Unity добавил JsonUtility в их API после 5.3.3 обновления. Забудьте обо всех сторонних библиотеках, если вы не делаете что-то более сложное. JsonUtility работает быстрее, чем другие библиотеки Json. Обновите Unity до версии 5.3.3 или выше, затем попробуйте решение ниже.

JsonUtility - это легкий API. Поддерживаются только простые типы. Он не поддерживает коллекции, такие как словарь. Единственным исключением является List. Он поддерживает List и List массив!

Если вам нужно сериализовать Dictionary или сделать что-то иное, чем простую сериализацию и десериализацию простых типов данных, используйте сторонний API. В противном случае продолжайте чтение.

Пример класса для сериализации:

[Serializable]
public class Player
{
    public string playerId;
    public string playerLoc;
    public string playerNick;
}

1. ОДИН ОБЪЕКТ ДАННЫХ (НЕРАБРЕЗНЫЙ JSON)

Сериализация части A:

Сериализуйте в Json с помощью метода public static string ToJson(object obj);.

Player playerInstance = new Player();
playerInstance.playerId = "8484239823";
playerInstance.playerLoc = "Powai";
playerInstance.playerNick = "Random Nick";

//Convert to Jason
string playerToJason = JsonUtility.ToJson(playerInstance);
Debug.Log(playerToJason);

Выход:

{"playerId":"8484239823","playerLoc":"Powai","playerNick":"Random Nick"}

Сериализация части B:

Сериализация в Json с перегрузкой метода public static string ToJson(object obj, bool prettyPrint);. Простая передача true в функцию JsonUtility.ToJson отформатирует данные. Сравните вывод ниже с выводом выше.

Player playerInstance = new Player();
playerInstance.playerId = "8484239823";
playerInstance.playerLoc = "Powai";
playerInstance.playerNick = "Random Nick";

//Convert to Jason
string playerToJason = JsonUtility.ToJson(playerInstance, true);
Debug.Log(playerToJason);

Выход:

{
    "playerId": "8484239823",
    "playerLoc": "Powai",
    "playerNick": "Random Nick"
}

Десериализация части A:

Десериализовать json с помощью перегрузки метода public static T FromJson(string json);.

string jsonString = "{\"playerId\":\"8484239823\",\"playerLoc\":\"Powai\",\"playerNick\":\"Random Nick\"}";
Player player = JsonUtility.FromJson<Player>(jsonString);
Debug.Log(player.playerLoc);

Десериализация части B:

Десериализовать json с помощью перегрузки метода public static object FromJson(string json, Type type);.

string jsonString = "{\"playerId\":\"8484239823\",\"playerLoc\":\"Powai\",\"playerNick\":\"Random Nick\"}";
Player player = (Player)JsonUtility.FromJson(jsonString, typeof(Player));
Debug.Log(player.playerLoc);

Десериализация части C:

Десериализовать JSON с помощью метода public static void FromJsonOverwrite(string json, object objectToOverwrite);. Когда используется JsonUtility.FromJsonOverwrite, новый экземпляр объекта, который вы десериализуете, не будет создан. Он просто повторно использует передаваемый вами экземпляр и перезаписывает его значения.

Это эффективно и должно использоваться по возможности.

Player playerInstance;
void Start()
{
    //Must create instance once
    playerInstance = new Player();
    deserialize();
}

void deserialize()
{
    string jsonString = "{\"playerId\":\"8484239823\",\"playerLoc\":\"Powai\",\"playerNick\":\"Random Nick\"}";

    //Overwrite the values in the existing class instance "playerInstance". Less memory Allocation
    JsonUtility.FromJsonOverwrite(jsonString, playerInstance);
    Debug.Log(playerInstance.playerLoc);
}

2. НЕСКОЛЬКО ДАННЫХ (ARRAY JSON)

Ваш Json содержит несколько объектов данных. Например, playerId появлялся более один раз. Unity JsonUtility не поддерживает массив, так как он все еще новый, но вы можете использовать вспомогательный класс от этого человека, чтобы массив работал с JsonUtility.

Создайте класс с именем JsonHelper. Скопируйте JsonHelper непосредственно снизу.

public static class JsonHelper
{
    public static T[] FromJson<T>(string json)
    {
        Wrapper<T> wrapper = JsonUtility.FromJson<Wrapper<T>>(json);
        return wrapper.Items;
    }

    public static string ToJson<T>(T[] array)
    {
        Wrapper<T> wrapper = new Wrapper<T>();
        wrapper.Items = array;
        return JsonUtility.ToJson(wrapper);
    }

    public static string ToJson<T>(T[] array, bool prettyPrint)
    {
        Wrapper<T> wrapper = new Wrapper<T>();
        wrapper.Items = array;
        return JsonUtility.ToJson(wrapper, prettyPrint);
    }

    [Serializable]
    private class Wrapper<T>
    {
        public T[] Items;
    }
}

Сериализация массива Json:

Player[] playerInstance = new Player[2];

playerInstance[0] = new Player();
playerInstance[0].playerId = "8484239823";
playerInstance[0].playerLoc = "Powai";
playerInstance[0].playerNick = "Random Nick";

playerInstance[1] = new Player();
playerInstance[1].playerId = "512343283";
playerInstance[1].playerLoc = "User2";
playerInstance[1].playerNick = "Rand Nick 2";

//Convert to Jason
string playerToJason = JsonHelper.ToJson(playerInstance, true);
Debug.Log(playerToJason);

Выход:

{
    "Items": [
        {
            "playerId": "8484239823",
            "playerLoc": "Powai",
            "playerNick": "Random Nick"
        },
        {
            "playerId": "512343283",
            "playerLoc": "User2",
            "playerNick": "Rand Nick 2"
        }
    ]
}

Десериализация массива Json:

string jsonString = "{\r\n    \"Items\": [\r\n        {\r\n            \"playerId\": \"8484239823\",\r\n            \"playerLoc\": \"Powai\",\r\n            \"playerNick\": \"Random Nick\"\r\n        },\r\n        {\r\n            \"playerId\": \"512343283\",\r\n            \"playerLoc\": \"User2\",\r\n            \"playerNick\": \"Rand Nick 2\"\r\n        }\r\n    ]\r\n}";

Player[] player = JsonHelper.FromJson<Player>(jsonString);
Debug.Log(player[0].playerLoc);
Debug.Log(player[1].playerLoc);

Выход:

Powai

User2


Если это массив Json с сервера, и вы не создали его вручную:

Возможно, вам придется добавить {"Items": перед полученной строкой, а затем добавить } в конце.

Я сделал для этого простую функцию:

string fixJson(string value)
{
    value = "{\"Items\":" + value + "}";
    return value;
}

тогда вы можете использовать его:

string jsonString = fixJson(yourJsonFromServer);
Player[] player = JsonHelper.FromJson<Player>(jsonString);

3. Дезериализовать строку json без класса & Десериализация Json с числовыми свойствами

Это Json, который начинается с числа или числовых свойств.

Например:

{ 
"USD" : {"15m" : 1740.01, "last" : 1740.01, "buy" : 1740.01, "sell" : 1744.74, "symbol" : "$"}, 

"ISK" : {"15m" : 179479.11, "last" : 179479.11, "buy" : 179479.11, "sell" : 179967, "symbol" : "kr"},

"NZD" : {"15m" : 2522.84, "last" : 2522.84, "buy" : 2522.84, "sell" : 2529.69, "symbol" : "$"}
}

Unity JsonUtility не поддерживает это, потому что свойство "15m" начинается с числа. Переменная класса не может начинаться с целого числа.

Загрузите SimpleJSON.cs из Unity вики.

Чтобы получить собственность в 15 млн. Долларов США:

var N = JSON.Parse(yourJsonString);
string price = N["USD"]["15m"].Value;
Debug.Log(price);

Чтобы получить свойство "15 м" ISK:

var N = JSON.Parse(yourJsonString);
string price = N["ISK"]["15m"].Value;
Debug.Log(price);

Чтобы получить свойство "15 м" от NZD:

var N = JSON.Parse(yourJsonString);
string price = N["NZD"]["15m"].Value;
Debug.Log(price);

Остальные свойства Json, которые не начинаются с цифры, могут обрабатываться Unity JsonUtility.


4. УСТРАНЕНИЕ НЕИСПРАВНОСТЕЙ JsonUtility:

Проблемы при сериализации с JsonUtility.ToJson?

Получение пустой строки или "{}" с помощью JsonUtility.ToJson?

. Убедитесь, что класс не является массивом. Если это так, используйте вспомогательный класс выше с JsonHelper.ToJson вместо JsonUtility.ToJson.

В. Добавьте [Serializable] в начало класса, который вы сериализуете.

C. Удалить свойство из класса. Например, в переменной public string playerId { get; set; } remove { get; set; }. Unity не может сериализовать это.

Проблемы при десериализации с JsonUtility.FromJson?

. Если вы получите Null, убедитесь, что Json не является массивом Json. Если это так, используйте вспомогательный класс выше с JsonHelper.FromJson вместо JsonUtility.FromJson.

В. Если вы получили NullReferenceException во время десериализации, добавьте [Serializable] в начало класса.

C. Любые другие проблемы, убедитесь, что ваш JSON действителен. Перейдите на этот сайт здесь и вставьте JSON. Он должен показать вам, если JSON действителен. Он также должен генерировать правильный класс с Json. Просто удалите remove { get; set; } из каждой переменной, а также добавьте [Serializable] в начало каждого сгенерированного класса.


Newtonsoft.Json:

Если по какой-либо причине необходимо использовать Newtonsoft.Json, ознакомьтесь с разветвленной версией Unity здесь. Обратите внимание, что вы можете столкнуться с падением при использовании определенной функции. Будьте осторожны.


Чтобы ответить на ваш вопрос:

Ваши исходные данные

 [{"playerId":"1","playerLoc":"Powai"},{"playerId":"2","playerLoc":"Andheri"},{"playerId":"3","playerLoc":"Churchgate"}]

Добавьте {"Items": впереди front и затем добавьте } на конце.

Код для этого:

serviceData = "{\"Items\":" + serviceData + "}";

Теперь у вас есть:

 {"Items":[{"playerId":"1","playerLoc":"Powai"},{"playerId":"2","playerLoc":"Andheri"},{"playerId":"3","playerLoc":"Churchgate"}]}

Чтобы сериализовать несколько данных из php в виде массивов, теперь вы можете сделать

public player[] playerInstance;
playerInstance = JsonHelper.FromJson<player>(serviceData);

playerInstance[0] ваши первые данные

playerInstance[1] ваши вторые данные

playerInstance[2] ваши третьи данные

или данные внутри класса с помощью playerInstance[0].playerLoc, playerInstance[1].playerLoc, playerInstance[2].playerLoc......

Вы можете использовать playerInstance.Length, чтобы проверить длину перед тем, как получить к ней доступ.

ПРИМЕЧАНИЕ. Удалите { get; set; } из класса player. Если у вас есть { get; set; }, он не будет работать. Unity JsonUtility НЕ работает с членами класса, которые определены как свойства.

Ответ 2

Предположим, вы получили JSON, как это

[
    {
        "type": "qrcode",
        "symbol": [
            {
                "seq": 0,
                "data": "HelloWorld9887725216",
                "error": null
            }
        ]
    }
]

Чтобы проанализировать вышеупомянутый JSON в единстве, вы можете создать модель JSON следующим образом.

[System.Serializable]
public class QrCodeResult
{
    public QRCodeData[] result;
}

[System.Serializable]
public class Symbol
{
    public int seq;
    public string data;
    public string error;
}

[System.Serializable]
public class QRCodeData
{
    public string type;
    public Symbol[] symbol;
}

А потом просто разобрать следующим образом...

var myObject = JsonUtility.FromJson<QrCodeResult>("{\"result\":" + jsonString.ToString() + "}");

Теперь вы можете изменить JSON/CODE в соответствии с вашими потребностями. https://docs.unity3d.com/Manual/JSONSerialization.html

Ответ 3

вам нужно добавить класс [System.Serializable] в PlayerItem, например:

using System;
[System.Serializable]
public class PlayerItem   {
    public string playerId;
    public string playerLoc;
    public string playerNick;
}

Ответ 4

Чтобы прочитать файл JSON, обратитесь к этому простому примеру.

Ваш файл JSON (StreamingAssets/Player.json)

{
    "Name": "MyName",
    "Level": 4
}

С# Script

public class Demo
{
    public void ReadJSON()
    {
        string path = Application.streamingAssetsPath + "/Player.json";
        string JSONString = File.ReadAllText(path);
        Player player = JsonUtility.FromJson<Player>(JSONString);
        Debug.Log(player.Name);
    }
}

[System.Serializable]
public class Player
{
    public string Name;
    public int Level;
}

Ответ 5

Не обрезайте [], и все должно быть в порядке. [] идентифицируйте массив JSON, который является именно тем, что вам нужно, чтобы выполнять итерацию его элементов.

Ответ 6

Как и @Maximiliangerhardt, MiniJson не имеет возможности десериализоваться должным образом. Я использовал JsonFx и работал как шарм. Работает с []

player[] p = JsonReader.Deserialize<player[]>(serviceData);
Debug.Log(p[0].playerId +" "+ p[0].playerLoc+"--"+ p[1].playerId + " " + p[1].playerLoc+"--"+ p[2].playerId + " " + p[2].playerLoc);

Ответ 7

Вы можете использовать Newtonsoft.Json, просто добавив Newtonsoft.dll в свой проект и использовать приведенный ниже скрипт

using System;
using Newtonsoft.Json;
using UnityEngine;

public class NewBehaviourScript : MonoBehaviour
{

    [Serializable]
    public class Person
    {
        public string id;
        public string name;
    }
    public Person[] person;

    private void Start()
    {
       var myjson = JsonConvert.SerializeObject(person);

        print(myjson);

    }
}

enter image description here

другое решение использует JsonHelper

using System;
using Newtonsoft.Json;
using UnityEngine;

public class NewBehaviourScript : MonoBehaviour
{

    [Serializable]
    public class Person
    {
        public string id;
        public string name;
    }
    public Person[] person;

    private void Start()
    {
        var myjson = JsonHelper.ToJson(person);

        print(myjson);

    }
}

enter image description here