简体   繁体   中英

Deserialize/Serialize arbitrary data type using Newtonsoft.Json

I have a data exchange framework that data will be formatted to JSON to pass to client from server using http.

Here is its' basic structure:

{
  status: 0,
  data: {name:"balbala",age:12}
  msg: "OK"
}

or:

{
  status: 0,
  data: [{name: "balbalba", age:12},{name:"another balbala", age:13}],
  msg: "OK"

}

or if something bad happens:

{
  status: -1,//the error code
  msg: "Sorry, internal error"
}

The basic idea is we use status as an error code, and check that error code before doing more stuff, and when it's not 0 just showing the msg which is the detail information of the error, but in the data field we want to carry arbitrary JSON format, mostly both array and object(key-values) , we can achieve that using gson in java, but when come to C# we don't know how to do that, is there a way of doing that with c# ?

here is I currently achieve, but with some errors.

//the Response structure Definition.
public class Respose
{
    public int status;
    public object data;
    public string msg;

    public Respose() { }
}

//serialize the HTTP text first time to a Response structure.
Respose resp = JsonConvert.DeserializeObject<Respose>(infoStr);

 //just check the status shutcut the processing when meet with a non-zero err-code
if(resp.status != 0)
{
        Debug.LogWarning(resp.msg);
        yield break;
}
//getting the data as json string so that we could deserialize it again
string levelArrayStr = JsonConvert.SerializeObject(resp.data);

//the real data-load we need.
List<Level> levelsFromServer = JsonConvert.DeserializeObject<List<Level>>(levelArrayStr);

here is the error:

JsonSerializationException: Unexpected token when deserializing object: StartObject. Path 'data[0]', line 1, position 21.
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject (System.Object newObject, Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonObjectContract contract, Newtonsoft.Json.Serialization.JsonProperty member, System.String id) (at C:/Project/Github/Json.Net.Unity3D/src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs:2423)
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, System.Object existingValue) (at C:/Project/Github/Json.Net.Unity3D/src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs:497)
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, System.Object existingValue) (at C:/Project/Github/Json.Net.Unity3D/src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs:293)
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType, Boolean checkAdditionalContent) (at C:/Project/Github/Json.Net.Unity3D/src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs:167)

You can use two (or three) separate classes to deserialize or you can use JObject .

public class Data
{
    public string Name;
    public int Age;
}

const string SINGLE = @"{
  status: 0,
  data: {name: ""balbala"",age:12},
  msg: ""OK""
}";


const string MULTI = @"{
  status: 0,
  data: [{name: ""balbala"",age:12},{name: ""another  balbala"",age:13}],
  msg: ""OK""
}";

const string ERROR = @"{
  status: 1,
  msg: ""Sorry, internal error""
}";

List<Data> loDataList = new List<Data>();
//JObject loJObject = JObject.Parse(ERROR);
//JObject loJObject = JObject.Parse(SINGLE);
JObject loJObject = JObject.Parse(MULTI);
if (loJObject.Value<int>("status") != 0)
{
    Debug.WriteLine(loJObject.Value<string>("msg"));
    return;
}

JToken loDataToken = loJObject["data"];
switch (loDataToken.Type)
{
    case JTokenType.Object:
        loDataList.Add(loJObject["data"].ToObject<Data>());
        break;
    case JTokenType.Array:
        loDataList = loJObject["data"].ToObject<List<Data>>();
        break;
}

foreach (var loData in loDataList)
{
    Debug.WriteLine("Name: {0} Age: {1}", loData.Name, loData.Age);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM