2008-12-30 104 views
111

我试图解析使用JSon.Net库一些JSON。文件似乎有点稀疏,我很困惑如何完成我所需要的。这是我需要解析的JSON格式。解析JSON使用Json.net

{ 
    "displayFieldName" : "OBJECT_NAME", 
    "fieldAliases" : { 
     "OBJECT_NAME" : "OBJECT_NAME", 
     "OBJECT_TYPE" : "OBJECT_TYPE" 
    }, 
    "positionType" : "point", 
    "reference" : { 
     "id" : 1111 
    }, 
    "objects" : [ { 
     "attributes" : { 
      "OBJECT_NAME" : "test name", 
      "OBJECT_TYPE" : "test type" 
     }, 
     "position" : { 
      "x" : 5, 
      "y" : 7 
     } 
    } ] 
} 

我真正需要的唯一数据就是对象数组中的东西。是否有可能对我来说,通过与类似的JSonTextReader解析,只是拉出我想要的东西,像OBJECT_TYPE和x和y位置?我似乎无法得到JSonTextReader工作,我希望它的方式,我觉得很少或几乎没有使用它的例子。

这似乎是第一序列化然后使用LINQ和我的对象将是理想的,我觉得每一个实例讨论第一个序列化JSON的,但我不知道我怎么会建立一个对象的这种结构。特别是对象数组,它需要像属性和位置对象的列表。我不知道如何编写我的对象,所以JSon.Net会知道如何序列化它。

我以为我可以写我自己的简单分析器刚才拉出来的一切,我需要到一个属性对象,我创建的,但我有一点运气。

希望这一切是有道理的,任何想法?

回答

129

我不知道JSON.NET,但它正常工作与JavaScriptSerializerSystem.Web.Extensions.dll(.NET 3.5 SP1):

using System.Collections.Generic; 
using System.Web.Script.Serialization; 
public class NameTypePair 
{ 
    public string OBJECT_NAME { get; set; } 
    public string OBJECT_TYPE { get; set; } 
} 
public enum PositionType { none, point } 
public class Ref 
{ 
    public int id { get; set; } 
} 
public class SubObject 
{ 
    public NameTypePair attributes { get; set; } 
    public Position position { get; set; } 
} 
public class Position 
{ 
    public int x { get; set; } 
    public int y { get; set; } 
} 
public class Foo 
{ 
    public Foo() { objects = new List<SubObject>(); } 
    public string displayFieldName { get; set; } 
    public NameTypePair fieldAliases { get; set; } 
    public PositionType positionType { get; set; } 
    public Ref reference { get; set; } 
    public List<SubObject> objects { get; set; } 
} 
static class Program 
{ 

    const string json = @"{ 
    ""displayFieldName"" : ""OBJECT_NAME"", 
    ""fieldAliases"" : { 
    ""OBJECT_NAME"" : ""OBJECT_NAME"", 
    ""OBJECT_TYPE"" : ""OBJECT_TYPE"" 
    }, 
    ""positionType"" : ""point"", 
    ""reference"" : { 
    ""id"" : 1111 
    }, 
    ""objects"" : [ 
    { 
     ""attributes"" : { 
     ""OBJECT_NAME"" : ""test name"", 
     ""OBJECT_TYPE"" : ""test type"" 
     }, 
     ""position"" : 
     { 
     ""x"" : 5, 
     ""y"" : 7 
     } 
    } 
    ] 
}"; 


    static void Main() 
    { 
     JavaScriptSerializer ser = new JavaScriptSerializer(); 
     Foo foo = ser.Deserialize<Foo>(json); 
    } 


} 

编辑:

Json.NET工程使用相同的JSON和类。

Foo foo = JsonConvert.DeserializeObject<Foo>(json); 

链接:Serializing and Deserializing JSON with Json.NET

+4

+1 for JavaScriptSerializer – 2009-11-27 00:26:05

+13

有没有办法将JSON字符串中的名称值对转换为现有的C#变量类型(例如Array或Dictionary?),以便不必创建特定/自定义类?在我的情况下,JSON字符串将在Ruby/Rails中生成... – Greg 2009-12-29 23:32:34

10

编辑:感谢Marc,阅读了struct vs class的问题,你是对的,谢谢!

我倾向于使用做你的描述,使用JSon.Net的静态方法下面的方法:

MyObject deserializedObject = JsonConvert.DeserializeObject<MyObject>(json); 

链接:Serializing and Deserializing JSON with Json.NET

对于对象名单,我建议使用通用列出你自己的小班,其中包含attributesposition班。您可以使用System.DrawingPoint结构(System.Drawing.PointSystem.Drawing.PointF浮点数)为您的X和Y.

对象创建后,它的容易让你对文本解析你”之后是数据再看看。

+0

结构很少会(如果有的话),在这里一个不错的选择;坚持对象(类)。 – 2008-12-31 11:11:56

0

您使用JSON类,然后调用GetData()功能。

/// <summary> 
/// This class encodes and decodes JSON strings. 
/// Spec. details, see http://www.json.org/ 
/// 
/// JSON uses Arrays and Objects. These correspond here to the datatypes ArrayList and Hashtable. 
/// All numbers are parsed to doubles. 
/// </summary> 
    using System; 
    using System.Collections; 
    using System.Globalization; 
    using System.Text; 

public class JSON 
{ 
    public const int TOKEN_NONE = 0; 
    public const int TOKEN_CURLY_OPEN = 1; 
    public const int TOKEN_CURLY_CLOSE = 2; 
    public const int TOKEN_SQUARED_OPEN = 3; 
    public const int TOKEN_SQUARED_CLOSE = 4; 
    public const int TOKEN_COLON = 5; 
    public const int TOKEN_COMMA = 6; 
    public const int TOKEN_STRING = 7; 
    public const int TOKEN_NUMBER = 8; 
    public const int TOKEN_TRUE = 9; 
    public const int TOKEN_FALSE = 10; 
    public const int TOKEN_NULL = 11; 

    private const int BUILDER_CAPACITY = 2000; 

    /// <summary> 
    /// Parses the string json into a value 
    /// </summary> 
    /// <param name="json">A JSON string.</param> 
    /// <returns>An ArrayList, a Hashtable, a double, a string, null, true, or false</returns> 
    public static object JsonDecode(string json) 
    { 
     bool success = true; 

     return JsonDecode(json, ref success); 
    } 

    /// <summary> 
    /// Parses the string json into a value; and fills 'success' with the successfullness of the parse. 
    /// </summary> 
    /// <param name="json">A JSON string.</param> 
    /// <param name="success">Successful parse?</param> 
    /// <returns>An ArrayList, a Hashtable, a double, a string, null, true, or false</returns> 
    public static object JsonDecode(string json, ref bool success) 
    { 
     success = true; 
     if (json != null) { 
      char[] charArray = json.ToCharArray(); 
      int index = 0; 
      object value = ParseValue(charArray, ref index, ref success); 
      return value; 
     } else { 
      return null; 
     } 
    } 

    /// <summary> 
    /// Converts a Hashtable/ArrayList object into a JSON string 
    /// </summary> 
    /// <param name="json">A Hashtable/ArrayList</param> 
    /// <returns>A JSON encoded string, or null if object 'json' is not serializable</returns> 
    public static string JsonEncode(object json) 
    { 
     StringBuilder builder = new StringBuilder(BUILDER_CAPACITY); 
     bool success = SerializeValue(json, builder); 
     return (success ? builder.ToString() : null); 
    } 

    protected static Hashtable ParseObject(char[] json, ref int index, ref bool success) 
    { 
     Hashtable table = new Hashtable(); 
     int token; 

     // { 
     NextToken(json, ref index); 

     bool done = false; 
     while (!done) { 
      token = LookAhead(json, index); 
      if (token == JSON.TOKEN_NONE) { 
       success = false; 
       return null; 
      } else if (token == JSON.TOKEN_COMMA) { 
       NextToken(json, ref index); 
      } else if (token == JSON.TOKEN_CURLY_CLOSE) { 
       NextToken(json, ref index); 
       return table; 
      } else { 

       // name 
       string name = ParseString(json, ref index, ref success); 
       if (!success) { 
        success = false; 
        return null; 
       } 

       // : 
       token = NextToken(json, ref index); 
       if (token != JSON.TOKEN_COLON) { 
        success = false; 
        return null; 
       } 

       // value 
       object value = ParseValue(json, ref index, ref success); 
       if (!success) { 
        success = false; 
        return null; 
       } 

       table[name] = value; 
      } 
     } 

     return table; 
    } 

    protected static ArrayList ParseArray(char[] json, ref int index, ref bool success) 
    { 
     ArrayList array = new ArrayList(); 

     // [ 
     NextToken(json, ref index); 

     bool done = false; 
     while (!done) { 
      int token = LookAhead(json, index); 
      if (token == JSON.TOKEN_NONE) { 
       success = false; 
       return null; 
      } else if (token == JSON.TOKEN_COMMA) { 
       NextToken(json, ref index); 
      } else if (token == JSON.TOKEN_SQUARED_CLOSE) { 
       NextToken(json, ref index); 
       break; 
      } else { 
       object value = ParseValue(json, ref index, ref success); 
       if (!success) { 
        return null; 
       } 

       array.Add(value); 
      } 
     } 

     return array; 
    } 

    protected static object ParseValue(char[] json, ref int index, ref bool success) 
    { 
     switch (LookAhead(json, index)) { 
      case JSON.TOKEN_STRING: 
       return ParseString(json, ref index, ref success); 
      case JSON.TOKEN_NUMBER: 
       return ParseNumber(json, ref index, ref success); 
      case JSON.TOKEN_CURLY_OPEN: 
       return ParseObject(json, ref index, ref success); 
      case JSON.TOKEN_SQUARED_OPEN: 
       return ParseArray(json, ref index, ref success); 
      case JSON.TOKEN_TRUE: 
       NextToken(json, ref index); 
       return true; 
      case JSON.TOKEN_FALSE: 
       NextToken(json, ref index); 
       return false; 
      case JSON.TOKEN_NULL: 
       NextToken(json, ref index); 
       return null; 
      case JSON.TOKEN_NONE: 
       break; 
     } 

     success = false; 
     return null; 
    } 

    protected static string ParseString(char[] json, ref int index, ref bool success) 
    { 
     StringBuilder s = new StringBuilder(BUILDER_CAPACITY); 
     char c; 

     EatWhitespace(json, ref index); 

     // " 
     c = json[index++]; 

     bool complete = false; 
     while (!complete) { 

      if (index == json.Length) { 
       break; 
      } 

      c = json[index++]; 
      if (c == '"') { 
       complete = true; 
       break; 
      } else if (c == '\\') { 

       if (index == json.Length) { 
        break; 
       } 
       c = json[index++]; 
       if (c == '"') { 
        s.Append('"'); 
       } else if (c == '\\') { 
        s.Append('\\'); 
       } else if (c == '/') { 
        s.Append('/'); 
       } else if (c == 'b') { 
        s.Append('\b'); 
       } else if (c == 'f') { 
        s.Append('\f'); 
       } else if (c == 'n') { 
        s.Append('\n'); 
       } else if (c == 'r') { 
        s.Append('\r'); 
       } else if (c == 't') { 
        s.Append('\t'); 
       } else if (c == 'u') { 
        int remainingLength = json.Length - index; 
        if (remainingLength >= 4) { 
         // parse the 32 bit hex into an integer codepoint 
         uint codePoint; 
         if (!(success = UInt32.TryParse(new string(json, index, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out codePoint))) { 
          return ""; 
         } 
         // convert the integer codepoint to a unicode char and add to string 
         s.Append(Char.ConvertFromUtf32((int)codePoint)); 
         // skip 4 chars 
         index += 4; 
        } else { 
         break; 
        } 
       } 

      } else { 
       s.Append(c); 
      } 

     } 

     if (!complete) { 
      success = false; 
      return null; 
     } 

     return s.ToString(); 
    } 

    protected static double ParseNumber(char[] json, ref int index, ref bool success) 
    { 
     EatWhitespace(json, ref index); 

     int lastIndex = GetLastIndexOfNumber(json, index); 
     int charLength = (lastIndex - index) + 1; 

     double number; 
     success = Double.TryParse(new string(json, index, charLength), NumberStyles.Any, CultureInfo.InvariantCulture, out number); 

     index = lastIndex + 1; 
     return number; 
    } 

    protected static int GetLastIndexOfNumber(char[] json, int index) 
    { 
     int lastIndex; 

     for (lastIndex = index; lastIndex < json.Length; lastIndex++) { 
      if ("-.eE".IndexOf(json[lastIndex]) == -1) { 
       break; 
      } 
     } 
     return lastIndex - 1; 
    } 

    protected static void EatWhitespace(char[] json, ref int index) 
    { 
     for (; index < json.Length; index++) { 
      if (" \t\n\r".IndexOf(json[index]) == -1) { 
       break; 
      } 
     } 
    } 

    protected static int LookAhead(char[] json, int index) 
    { 
     int saveIndex = index; 
     return NextToken(json, ref saveIndex); 
    } 

    protected static int NextToken(char[] json, ref int index) 
    { 
     EatWhitespace(json, ref index); 

     if (index == json.Length) { 
      return JSON.TOKEN_NONE; 
     } 

     char c = json[index]; 
     index++; 
     switch (c) { 
      case '{': 
       return JSON.TOKEN_CURLY_OPEN; 
      case '}': 
       return JSON.TOKEN_CURLY_CLOSE; 
      case '[': 
       return JSON.TOKEN_SQUARED_OPEN; 
      case ']': 
       return JSON.TOKEN_SQUARED_CLOSE; 
      case ',': 
       return JSON.TOKEN_COMMA; 
      case '"': 
       return JSON.TOKEN_STRING; 
      case '0': case '1': case '2': case '3': case '4': 
      case '5': case '6': case '7': case '8': case '9': 
      case '-': 
       return JSON.TOKEN_NUMBER; 
      case ':': 
       return JSON.TOKEN_COLON; 
     } 
     index--; 

     int remainingLength = json.Length - index; 

     // false 
     if (remainingLength >= 5) { 
      if (json[index] == 'f' && 
       json[index + 1] == 'a' && 
       json[index + 2] == 'l' && 
       json[index + 3] == 's' && 
       json[index + 4] == 'e') { 
       index += 5; 
       return JSON.TOKEN_FALSE; 
      } 
     } 

     // true 
     if (remainingLength >= 4) { 
      if (json[index] == 't' && 
       json[index + 1] == 'r' && 
       json[index + 2] == 'u' && 
       json[index + 3] == 'e') { 
       index += 4; 
       return JSON.TOKEN_TRUE; 
      } 
     } 

     // null 
     if (remainingLength >= 4) { 
      if (json[index] == 'n' && 
       json[index + 1] == 'u' && 
       json[index + 2] == 'l' && 
       json[index + 3] == 'l') { 
       index += 4; 
       return JSON.TOKEN_NULL; 
      } 
     } 

     return JSON.TOKEN_NONE; 
    } 

    protected static bool SerializeValue(object value, StringBuilder builder) 
    { 
     bool success = true; 

     if (value is string) { 
      success = SerializeString((string)value, builder); 
     } else if (value is Hashtable) { 
      success = SerializeObject((Hashtable)value, builder); 
     } else if (value is ArrayList) { 
      success = SerializeArray((ArrayList)value, builder); 
     } else if ((value is Boolean) && ((Boolean)value == true)) { 
      builder.Append("true"); 
     } else if ((value is Boolean) && ((Boolean)value == false)) { 
      builder.Append("false"); 
     } else if (value is ValueType) { 
      // thanks to ritchie for pointing out ValueType to me 
      success = SerializeNumber(Convert.ToDouble(value), builder); 
     } else if (value == null) { 
      builder.Append("null"); 
     } else { 
      success = false; 
     } 
     return success; 
    } 

    protected static bool SerializeObject(Hashtable anObject, StringBuilder builder) 
    { 
     builder.Append("{"); 

     IDictionaryEnumerator e = anObject.GetEnumerator(); 
     bool first = true; 
     while (e.MoveNext()) { 
      string key = e.Key.ToString(); 
      object value = e.Value; 

      if (!first) { 
       builder.Append(", "); 
      } 

      SerializeString(key, builder); 
      builder.Append(":"); 
      if (!SerializeValue(value, builder)) { 
       return false; 
      } 

      first = false; 
     } 

     builder.Append("}"); 
     return true; 
    } 

    protected static bool SerializeArray(ArrayList anArray, StringBuilder builder) 
    { 
     builder.Append("["); 

     bool first = true; 
     for (int i = 0; i < anArray.Count; i++) { 
      object value = anArray[i]; 

      if (!first) { 
       builder.Append(", "); 
      } 

      if (!SerializeValue(value, builder)) { 
       return false; 
      } 

      first = false; 
     } 

     builder.Append("]"); 
     return true; 
    } 

    protected static bool SerializeString(string aString, StringBuilder builder) 
    { 
     builder.Append("\""); 

     char[] charArray = aString.ToCharArray(); 
     for (int i = 0; i < charArray.Length; i++) { 
      char c = charArray[i]; 
      if (c == '"') { 
       builder.Append("\\\""); 
      } else if (c == '\\') { 
       builder.Append("\\\\"); 
      } else if (c == '\b') { 
       builder.Append("\\b"); 
      } else if (c == '\f') { 
       builder.Append("\\f"); 
      } else if (c == '\n') { 
       builder.Append("\\n"); 
      } else if (c == '\r') { 
       builder.Append("\\r"); 
      } else if (c == '\t') { 
       builder.Append("\\t"); 
      } else { 
       int codepoint = Convert.ToInt32(c); 
       if ((codepoint >= 32) && (codepoint <= 126)) { 
        builder.Append(c); 
       } else { 
        builder.Append("\\u" + Convert.ToString(codepoint, 16).PadLeft(4, '0')); 
       } 
      } 
     } 

     builder.Append("\""); 
     return true; 
    } 

    protected static bool SerializeNumber(double number, StringBuilder builder) 
    { 
     builder.Append(Convert.ToString(number, CultureInfo.InvariantCulture)); 
     return true; 
    } 
} 

//parse and show entire json in key-value pair 
    Hashtable HTList = (Hashtable)JSON.JsonDecode("completejsonstring"); 
     public void GetData(Hashtable HT) 
     {   
      IDictionaryEnumerator ienum = HT.GetEnumerator(); 
      while (ienum.MoveNext()) 
      { 
       if (ienum.Value is ArrayList) 
       { 
        ArrayList arnew = (ArrayList)ienum.Value; 
        foreach (object obj in arnew)      
        { 
         Hashtable hstemp = (Hashtable)obj; 
         GetData(hstemp); 
        } 
       } 
       else 
       { 
        Console.WriteLine(ienum.Key + "=" + ienum.Value); 
       } 
      } 
     } 
4
/* 
    * This method takes in JSON in the form returned by javascript's 
    * JSON.stringify(Object) and returns a string->string dictionary. 
    * This method may be of use when the format of the json is unknown. 
    * You can modify the delimiters, etc pretty easily in the source 
    * (sorry I didn't abstract it--I have a very specific use). 
    */ 
    public static Dictionary<string, string> jsonParse(string rawjson) 
    { 
     Dictionary<string, string> outdict = new Dictionary<string, string>(); 
     StringBuilder keybufferbuilder = new StringBuilder(); 
     StringBuilder valuebufferbuilder = new StringBuilder(); 
     StringReader bufferreader = new StringReader(rawjson); 

     int s = 0; 
     bool reading = false; 
     bool inside_string = false; 
     bool reading_value = false; 
     //break at end (returns -1) 
     while (s >= 0) 
     { 
      s = bufferreader.Read(); 
      //opening of json 
      if (!reading) 
      { 
       if ((char)s == '{' && !inside_string && !reading) reading = true; 
       continue; 
      } 
      else 
      { 
       //if we find a quote and we are not yet inside a string, advance and get inside 
       if (!inside_string) 
       { 
        //read past the quote 
        if ((char)s == '\"') inside_string = true; 
        continue; 
       } 
       if (inside_string) 
       { 
        //if we reached the end of the string 
        if ((char)s == '\"') 
        { 
         inside_string = false; 
         s = bufferreader.Read(); //advance pointer 
         if ((char)s == ':') 
         { 
          reading_value = true; 
          continue; 
         } 
         if (reading_value && (char)s == ',') 
         { 
          //we know we just ended the line, so put itin our dictionary 
          if (!outdict.ContainsKey(keybufferbuilder.ToString())) outdict.Add(keybufferbuilder.ToString(), valuebufferbuilder.ToString()); 
          //and clear the buffers 
          keybufferbuilder.Clear(); 
          valuebufferbuilder.Clear(); 
          reading_value = false; 
         } 
         if (reading_value && (char)s == '}') 
         { 
          //we know we just ended the line, so put itin our dictionary 
          if (!outdict.ContainsKey(keybufferbuilder.ToString())) outdict.Add(keybufferbuilder.ToString(), valuebufferbuilder.ToString()); 
          //and clear the buffers 
          keybufferbuilder.Clear(); 
          valuebufferbuilder.Clear(); 
          reading_value = false; 
          reading = false; 
          break; 
         } 
        } 
        else 
        { 
         if (reading_value) 
         { 
          valuebufferbuilder.Append((char)s); 
          continue; 
         } 
         else 
         { 
          keybufferbuilder.Append((char)s); 
          continue; 
         } 
        } 
       } 
       else 
       { 
        switch ((char)s) 
        { 
         case ':': 
          reading_value = true; 
          break; 
         default: 
          if (reading_value) 
          { 
           valuebufferbuilder.Append((char)s); 
          } 
          else 
          { 
           keybufferbuilder.Append((char)s); 
          } 
          break; 
        } 
       } 
      } 
     } 
     return outdict; 
    } 
3

(这个问题提出了较高的搜索引擎上的结果,但我最终使用了不同的方法。如果添加一个回答这个老问题的其他人有类似的问题阅读)

您可以Json.Net解决这个问题,使扩展方法来处理项目要循环:

public static Tuple<string, int, int> ToTuple(this JToken token) 
{ 
    var type = token["attributes"]["OBJECT_TYPE"].ToString(); 
    var x = token["position"]["x"].Value<int>(); 
    var y = token["position"]["y"].Value<int>(); 
    return new Tuple<string, int, int>(type, x, y); 
} 

然后访问的数据是这样的:(场景:写入控制台):

var tuples = JObject.Parse(myJsonString)["objects"].Select(item => item.ToTuple()).ToList(); 
tuples.ForEach(t => Console.WriteLine("{0}: ({1},{2})", t.Item1, t.Item2, t.Item3));