Unity에서 Json 및 Json 배열 직렬화 및 역 직렬화


97

을 사용하여 PHP 파일에서 Unity로 보내는 항목 목록이 있습니다 WWW.

WWW.text외모가 좋아 :

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

어디 여분을 잘라 []으로부터 string. 을 사용하여 구문 분석을 시도 Boomlagoon.JSON하면 첫 번째 개체 만 검색됩니다. 나는에있는 것을 발견 deserialize()목록 및 MiniJSON을 가져 왔습니다.

그러나 나는 deserialize()이 목록에 대해 혼란 스럽습니다 . 모든 JSON 개체를 반복하고 데이터를 검색하고 싶습니다. C #을 사용하여 Unity에서 어떻게 할 수 있습니까?

내가 사용하는 수업은

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

트리밍 후 []MiniJSON을 사용하여 json을 구문 분석 할 수 있습니다. 그러나 그것은 첫 번째 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));
}

감사!


왜 바깥 쪽을 제거 않았다 []? 그것이 목록을 만드는 것입니다. 그만 제거하고 배열이나 목록으로 역 직렬화하면 괜찮을 것으로 기대합니다. 시도한 코드를 게시하십시오.
Jon Skeet

역 직렬화에 사용 된 클래스를 보여줍니다. 형식이 이상합니다. 두 번째 playerId가 중괄호로 둘러싸여 있지 않은 이유는 무엇입니까? 그것은 뭔가, 등의 목록에 직렬화한다 List<PlayerLocation>이 때문에, 이다 배열.
Maximilian Gerhardt

@MaximilianGerhardt 죄송합니다 중괄호가 오타였습니다. 질문에서 수정하고 코드도 추가했습니다. 감사.
dil33pm

1
여기이 도서관 탈 분열 화를 처리 하는 방법에 대한 이해에 문제가 있다고 생각 합니다. 일반적인 역 직렬화는 아니지만 (에서 볼 수 있듯이 Newtonsoft.Json) Json.Deserialize()항상 a IDictionary<string,object>를 반환하고 List<object>. stackoverflow.com/a/22745634/5296568을 보십시오 . 가급적이면 익숙한 deserialization을 수행하는 더 나은 JSON deserializer를 얻으십시오.
Maximilian Gerhardt

@MaximilianGerhardt 나는 IDictionary<string,object>. 나는 가치를 얻을 수 있지만 첫 번째 KeyValuePair<>.
dil33pm

답변:


247

Unity는 5.3.3 업데이트 이후 API 에 JsonUtility 를 추가 했습니다 . 더 복잡한 작업을 수행하지 않는 한 모든 타사 라이브러리는 잊어 버리십시오. JsonUtility는 다른 Json 라이브러리보다 빠릅니다. Unity 5.3.3 버전 이상으로 업데이트 한 다음 아래 해결 방법을 시도해보세요.

JsonUtility경량 API입니다. 단순 유형 만 지원됩니다. 사전과 같은 컬렉션 은 지원 하지 않습니다 . 한 가지 예외는 List. 지원 ListList배열!

a를 직렬화 Dictionary하거나 단순 데이터 유형을 직렬화 및 역 직렬화하는 것 이외의 작업을 수행 해야하는 경우 타사 API를 사용하십시오. 그렇지 않으면 계속 읽으십시오.

직렬화 할 예제 클래스 :

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

1. 하나의 데이터 개체 (배열이 아닌 JSON)

파트 A 직렬화 :

public static string ToJson(object obj);메서드 를 사용하여 Json으로 직렬화 합니다 .

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

//Convert to JSON
string playerToJson = JsonUtility.ToJson(playerInstance);
Debug.Log(playerToJson);

출력 :

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

파트 B 직렬화 :

public static string ToJson(object obj, bool prettyPrint);메서드 오버로드 를 사용하여 Json으로 직렬화 합니다 . 간단히 전달 true받는 JsonUtility.ToJson기능은 데이터를 포맷합니다. 아래 출력을 위의 출력과 비교하십시오.

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

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

출력 :

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

파트 A 직렬화 해제 :

public static T FromJson(string json);메서드 오버로드를 사용하여 json을 역 직렬화합니다 .

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

파트 B 역 직렬화 :

public static object FromJson(string json, Type type);메서드 오버로드를 사용하여 json을 역 직렬화합니다 .

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

파트 C 역 직렬화 :

public static void FromJsonOverwrite(string json, object objectToOverwrite);메서드로 json을 역 직렬화 합니다 . 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 이상 나타났습니다 . 유니티의는 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 JSON
string playerToJson = JsonHelper.ToJson(playerInstance, true);
Debug.Log(playerToJson);

출력 :

{
    "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

사용자 2


이것이 서버의 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.csUnity의 위키 에서 다운로드하십시오 .

USD의 "15m"속성을 얻으려면 :

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

ISK의 "15m"속성을 얻으려면 :

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

NZD의 "15m"자산을 얻으려면 :

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

숫자로 시작하지 않는 나머지 Json 속성은 Unity의 JsonUtility에서 처리 할 수 ​​있습니다.


4. JsonUtility 문제 해결 :

직렬화 할 때 문제가 JsonUtility.ToJson있습니까?

빈 문자열 또는 " {}"를 JsonUtility.ToJson?

. 클래스가 배열이 아닌지 확인하십시오. 그렇다면 위의 도우미 클래스 JsonHelper.ToJsonJsonUtility.ToJson.

B . [Serializable]직렬화중인 클래스의 맨 위에 추가하십시오 .

C . 클래스에서 속성을 제거합니다. 예를 들어, 변수, public string playerId { get; set; } 제거 { get; set; } . Unity는 이것을 직렬화 할 수 없습니다.

역 직렬화 할 때 문제가 JsonUtility.FromJson있습니까?

. 를 얻으면 NullJson이 Json 배열이 아닌지 확인하십시오. 그렇다면 위의 도우미 클래스 JsonHelper.FromJsonJsonUtility.FromJson.

B . NullReferenceException역 직렬화하는 동안 얻으면 [Serializable]클래스 맨 위에 추가하십시오 .

C. 기타 문제는 json이 유효한지 확인하십시오. 여기이 사이트로 이동 하여 json을 붙여 넣으십시오. json이 유효한지 표시해야합니다. 또한 Json으로 적절한 클래스를 생성해야합니다. 각 변수에서 제거를 제거 { get; set; } 하고 [Serializable]생성 된 각 클래스의 맨 위에 추가하십시오 .


Newtonsoft.Json :

어떤 이유로 Newtonsoft.Json을 사용해야 한다면 여기 에서 Unity 용 포크 버전을 확인 하세요 . 특정 기능을 사용하면 충돌이 발생할 수 있습니다. 조심해.


질문에 답하려면 :

원래 데이터는

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

추가 {"Items":프런트 는 다음의 추가 } 상기 그것의.

이를 수행하는 코드 :

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액세스하기 전에 길이를 확인하는 데 사용할 수 있습니다 .

참고 : 클래스 에서 제거하십시오 . 가있는 경우 작동하지 않습니다. Unity 는 속성 으로 정의 된 클래스 멤버와 작동 하지 않습니다 .{ get; set; }player{ get; set; }JsonUtility


mysql사용하여 PHP 에서 쿼리 행 배열을 반환합니다 json_encode($row). 따라서 응답은 형식의 여러 JSONObject로 구성됩니다 [{"playerId":"1","playerLoc":"Powai"},{"playerId":"2","playerLoc":"Andheri"},{"playerId":"3","playerLoc":"Churchgate"}]. JsonUtility를 시도했지만 개체를 ​​deserialize하고 개별 json 개체를 가져올 수 없습니다. 저를 도울 수 있다면.
dil33pm

2
위에 게시 한 코드를보십시오. 이 작업을 수행하는 세 가지 방법을 보여줍니다 JsonUtility.FromJson. 수업 { get; set; }에서 제거하라고 말하는 것을 잊었습니다 player. 을 가지고 있으면 { get; set; }작동하지 않습니다. player위에 게시 한 수업과 수업을 비교 하면 내가 말하는 내용을 이해할 수 있습니다.
프로그래머

1
문제 없어요. Unity가 어레이에 대한 지원을 추가 할 때 (곧 출시 예정)이를 편집 할 것이므로 더 이상 Helper 클래스가 필요하지 않습니다.
프로그래머

1
나는 "모든 타사 라이브러리에 대해 잊어 버려"라고 말하지 않을 것입니다. JsonUtility에는 제한이 있습니다. 작업을 수행 할 수있는 JSON 개체는 반환하지 않습니다. 예를 들어, json 파일을 받고 "성공"키를 사용할 수 있는지 확인하고 싶습니다. 할 수 없습니다. JsonUtility를 사용하려면 소비자가 json 파일의 정확한 내용을 알고 있어야합니다. 또한 사전 변환기가 없습니다. 따라서 좋은 일을하지만 타사 사용이 여전히 필요합니다.
Everts

2
사용 JsonHelper. 괜찮아. Json을 만들면 별도의 단계없이 json을 읽을 수도 있습니다. 추가 작업을 수행해야하는 유일한 시간은 서버에서 json 배열을 수신하고 솔루션에 포함되어있는 경우입니다. 없는 또 다른 방법 JsonHelper은 클래스를 다른 클래스에 넣은 다음 List. 이것은 대부분의 사람들에게 효과가 있습니다. 게임 데이터를 저장하고로드하는 방법을 찾고 있다면 를 참조 하십시오 . 한 줄의 코드로로드하고 저장합니다.
프로그래머

17

다음과 같은 JSON이 있다고 가정합니다.

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

위의 JSON을 Unity로 구문 분석하려면 다음과 같이 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


이것은 실제로 매우 잘 작동하며 배열이 아닌 Symbol과 같은 클래스에서도 작동합니다.
Gennon

4
나는 단결 2018와이 노력하고있어하지만이 작동하지 않습니다 배열은 구문 분석되지 않습니다
진 마이클 Celerier

Unity 2018 및 2019에서 사용됩니다. 훌륭하게 작동합니다. 다음과 같은 어레이 데이터에 액세스합니다. Debug.Log(myObject.result[0].symbol[0].data);또는 for(var i = 0; i <= myObject.result.Length - 1; i ++) { Debug.Log(myObject.result[i].type); }또는foreach (var item in myObject.result) { Debug.Log(item.type); }
Towerss

@Narottam 고얄, 당신의 방법은이 스레드에 나에 의해이 답변을 참조, 또한 일부의 경우, 초보자를위한 매우 어려운 솔루션에서 작동하지 않는 링크
Juned 칸 Momin

@JunedKhanMomin 귀하의 답변은 기본적으로 동일하지만 여기 에이 질문이 특정 JSON 데이터 의 루트 수준 배열 에 관한 사실을 언급하지 않고 있습니다. 일반적으로 프로그래머의 대답 을 참조하십시오 .
derHugo

2

다음 과 같이 클래스 에 추가 [System.Serializable]해야 PlayerItem합니다.

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

0

트림하지 마십시오 []. 그러면 괜찮을 것입니다. []요소를 반복 할 수 있도록 정확히 필요한 JSON 배열을 식별하십시오.


0

@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);

0

JSON 파일을 읽으려면이 간단한 예제를 참조하십시오.

JSON 파일 (StreamingAssets / Player.json)

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

C # 스크립트

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;
}

1
어레이는 어떻습니까? 그리고이 답변 은 3 년 전에 받아 들여진 답변 에서 이미 충족되지 않은 무엇을 추가 합니까?
derHugo

0

당신이 사용할 수있는 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);

    }
}

여기에 이미지 설명 입력

또 다른 해결책은 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);

    }
}

여기에 이미지 설명 입력


0

Vector3를 사용하는 경우 이것이 내가 한 일입니다.

1- 클래스를 만듭니다 Name it Player

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[Serializable]
public class Player
{
    public Vector3[] Position;

}

2- 그런 다음 이렇게 부릅니다.

if ( _ispressed == true)
        {
            Player playerInstance = new Player();
            playerInstance.Position = newPos;
            string jsonData = JsonUtility.ToJson(playerInstance);

            reference.Child("Position" + Random.Range(0, 1000000)).SetRawJsonValueAsync(jsonData);
            Debug.Log(jsonData);
            _ispressed = false;
        }

3- 그리고 이것은 결과입니다

"위치": [{ "x":-2.8567452430725099, "y":-2.4323320388793947, "z": 0.0}]}


0

Unity <= 2019

Narottam Goyal은 배열을 json 객체로 래핑 한 다음 구조체로 역 직렬화하는 좋은 아이디어를 가지고있었습니다. 다음은 매번 새로운 클래스를 만드는 대신 Generics를 사용하여 모든 유형의 배열에 대해이 문제를 해결합니다.

[System.Serializable]
private struct JsonArrayWrapper<T> {
    public T wrap_result;
}

public static T ParseJsonArray<T>(string json) {
    var temp = JsonUtility.FromJson<JsonArrayWrapper<T>>("{\" wrap_result\":" + json + "}");
    return temp.wrap_result;
}

다음과 같은 방법으로 사용할 수 있습니다.

string[] options = ParseJsonArray<string[]>(someArrayOfStringsJson);

Unity 2020

Unity 2020에는 훨씬 더 나은 json 라이브러리 인 공식 newtonsoft 패키지가 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.