How to access Json data without unknown key?

前端 未结 2 461
情话喂你
情话喂你 2021-01-29 10:42
public static string RESTToJsonConverter(string incoming_data){
    string data = "[";
    int i = 0;
    Debug.Log("incoming_data"+incoming_data);
          


        
相关标签:
2条回答
  • 2021-01-29 10:59

    For your specific case I would go the other way round:

    The root field name usually doesn't matter so if you remove the trailing } and start the string from the second { you would have

    {
        "assetName": "avatar",
        "id": "-M4qRmfnFya7bC43Ujye",
        "imageName": "icon_avatar",
        "name": "Bob",
        "objName": "Bobby",
        "point": "-M4vZRY9vhKs65n5L_Gk",
        "versionNumber": "3"
    }
    

    which you can simply create a c# class for

    [Serializable]
    public class Data
    {
        public string assetName;
        public string id;
        public string imageName;
        public string name;
        public string objName;
        public string point;
        public string versionNumber;
    }
    

    and then you could use JsonUtility

    public static Data RESTToJsonConverter(string incoming_data)
    {
        Debug.Log($"incoming_data:/n{incoming_data}");
    
        // remove everything before the SECOND occurrence of '{'
        // remove last occurrence of '}'
        var startIndex = incoming_data.IndexOf('{', incoming_data.IndexOf('{') + 1);
        var endIndex = incoming_data.LastIndexOf('}') - 1;
        var json = incoming_data.Substring(startIndex, endIndex - startIndex);
    
        // then remove leading or trailing whitespace
        json = json.Trim();
        
        Debug.Log($"json:/n{json}");
       
        var data = JsonUtility.FromJson<Data>(json);
    
        return data;
    }
    

    Update

    You now updated your question content so now the data comes as a Dictionary of data objects.

    In this case you could use Newtonsoft Json.NET which directly supports (de)serialization of Dictionary like e.g.

    [Serializable]
    public class Data
    {
        public string assetName;
        public string id;
        public string imageName;
        public string name;
        public string objName;
        public string point;
        public string versionNumber;
    }
    

    and then do something like

    public static Dictionary<string, Data> RESTToJsonConverter(string incoming_data)
    {
        Debug.Log($"incoming_data:/n{incoming_data}");
       
        var data = JsonConvert.DeserializeObject<Dictionary<string, Data>(json);
    
        return data;
    }
    

    then you can do e.g.

    var datas = RESTToJsonConverter(receivedRawData);
    foreach(var data in data.Values)
    {
        Debug.Log(data.id);
    }
    
    0 讨论(0)
  • 2021-01-29 11:11

    I suppose, your question is about the deserialization of the JSON with non-unique keys. If it is, take to look over here: How to deserialize JSON with duplicate property names in the same object

    In your case, the solution should contain the following:

    declaring your contract:

    public class Data
    {
            public string assetName{get;set;}
            public string id{get;set;}
            public string imageName{get;set;}
            public string name{get;set;}
            public string objName{get;set;}
            public string point{get;set;}
            public string versionNumber{get;set;}
    }
    

    your "custom deserializer" :)

    public static JToken DeserializeAndCombineDuplicates(JsonTextReader reader)
    {
        if (reader.TokenType == JsonToken.None)
        {
            reader.Read();
        }
    
        if (reader.TokenType == JsonToken.StartObject)
        {
            reader.Read();
            JObject obj = new JObject();
            while (reader.TokenType != JsonToken.EndObject)
            {
                string propName = (string)reader.Value;
                reader.Read();
                JToken newValue = DeserializeAndCombineDuplicates(reader);
    
                JToken existingValue = obj[propName];
                if (existingValue == null)
                {
                    obj.Add(new JProperty(propName, newValue));
                }
                else if (existingValue.Type == JTokenType.Array)
                {
                    CombineWithArray((JArray)existingValue, newValue);
                }
                else // Convert existing non-array property value to an array
                {
                    JProperty prop = (JProperty)existingValue.Parent;
                    JArray array = new JArray();
                    prop.Value = array;
                    array.Add(existingValue);
                    CombineWithArray(array, newValue);
                }
    
                reader.Read();
            }
            return obj;
        }
    
        if (reader.TokenType == JsonToken.StartArray)
        {
            reader.Read();
            JArray array = new JArray();
            while (reader.TokenType != JsonToken.EndArray)
            {
                array.Add(DeserializeAndCombineDuplicates(reader));
                reader.Read();
            }
            return array;
        }
    
        return new JValue(reader.Value);
    }   
    private static void CombineWithArray(JArray array, JToken value)
    {
        if (value.Type == JTokenType.Array)
        {
            foreach (JToken child in value.Children())
                array.Add(child);
        }
        else
        {
            array.Add(value);
        }
    }
    

    some code to get a Dictionary<string, Data[]> as a result type

    using (StringReader sr = new StringReader(json))
    using (JsonTextReader reader = new JsonTextReader(sr))
    {
        var parsed = DeserializeAndCombineDuplicates(reader).ToObject<Dictionary<string, Data[]>>();
        
        if(parsed!=null)
        {
            parsed
                .ToList()
                .ForEach(x=>Console.WriteLine("\r\nkey={0}\r\nvalues:\r\n{1}"
                                    , x.Key
                                    , string.Join("\r\n", x.Value
                                                  .Select(z=>string.Join("\t\t", z.name, z.id, z.objName))
                                                  .ToArray())));
        } else Console.WriteLine("No way, dude!");
    }
    

    The full solution is placed here: https://dotnetfiddle.net/lYBytk

    0 讨论(0)
提交回复
热议问题