c#:Json字符串转成xml对象

没看到.net framework中有这样的功能, 懒得到处找了, 索性花点时间自己写一个

/*
 * Created by SharpDevelop.
 * Date: 2013/6/24
 * User: sliencer
 * Time: 21:54
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;

namespace JsonDecoder
{
    class Program
    {
        public static void Main(string[] args)
        {
            int i=0;
            foreach (String element in inputs) {
                JS_Value v=JsonDecoder.Decode(element);
                if (v == null)
                    throw Error.InvalidJsonStream;
                String s=v.ToString();
                XmlWriterSettings settings =new XmlWriterSettings();
                settings.Indent = true;
                settings.Encoding = Encoding.UTF8;
                XmlWriter wri = XmlWriter.Create("Output" + (i++) + ".xml", settings);
                v.ToXml(wri, true, "JSon");
                wri.Close();
            }
        }
        static String[] inputs=new string[]{
        /*自己找几个json测试一下, 我的是从网站随便找来的, 担心版权问题, 就去掉了*/
        @"""test1""", @"""test2""", @"""test3"""
        };
    }
    public abstract class JS_Value
    {
        public abstract void ToXml(XmlWriter p_wri, bool p_bCreateElement, String p_strElementName);
    }
    public static class XmlHelper
    {
        public static String ToValidXmlName(String p_name)
        {
            /*
             * http://www.w3.org/TR/REC-xml/#NT-Name
                NameStartChar       ::=       ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
                NameChar       ::=       NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
             */
            string patNameStartChar = @":|[A-Z]|_|[a-z]|[\xC0-\xD6]|[\xD8-\xF6]|[\xF8-\u02FF]|[\u0370-\u037D]|[\u037F-\u1FFF]|[\u200C-\u200D]|[\u2070-\u218F]|[\u2C00-\u2FEF]|[\u3001-\uD7FF]|[\uF900-\uFDCF]|[\uFDF0-\uFFFD]";
            string patNameChar = patNameStartChar +"|" + @"-|\.|[0-9]|\xB7|[\u0300-\u036F]|[\u203F-\u2040]";
            String pat=@"^(" + patNameStartChar + ")" + "(" + patNameChar + ")*$";
            if (Regex.Match(p_name, pat, RegexOptions.Singleline).Success)
                return p_name;
            else
            {
                StringBuilder bld=new StringBuilder();
                for (int i=0;i<p_name.Length;i++)
                {
                    bool bMatch=false;
                    if (i==0)
                        bMatch = Regex.Match(p_name[i].ToString(), patNameStartChar,  RegexOptions.Singleline).Success;
                    else
                        bMatch = Regex.Match(p_name[i].ToString(), patNameChar,  RegexOptions.Singleline).Success;
                    if(bMatch)
                        bld.Append(p_name[i]);
                    else
                        bld.AppendFormat("_x{0:x}_", (int)p_name[i]);
                }
                return bld.ToString();
            }
        }
        public static void WriteStartElement_auto(this XmlWriter wri, String p_strName)
        {
            if (p_strName.Contains(":"))
            {
                String prefix=p_strName.Substring(0, p_strName.LastIndexOf(':'));
                string localName=p_strName.Substring(p_strName.LastIndexOf(':')+1);
                if(String.IsNullOrEmpty(localName))
                {
                    localName = p_strName.Substring(0, p_strName.Length-1);
                    prefix = "";
                }                
                wri.WriteStartElement(localName, prefix);
            } else
                wri.WriteStartElement(p_strName);
        }
    }
    public class JS_String : JS_Value
    {
        public String RawValue{get;set;}
        public String Value{get;set;}
        public override string ToString()
        {
            return RawValue;
        }
        public override void ToXml(XmlWriter p_wri, bool p_bCreateElement, String p_strElementName)
        {
            String strEleName=XmlHelper.ToValidXmlName(String.IsNullOrEmpty(p_strElementName)? "Value" : p_strElementName);
            if (p_bCreateElement)
            {
                p_wri.WriteStartElement_auto(strEleName);
            }
            p_wri.WriteAttributeString("type", "string");
            p_wri.WriteString(Value);
            if (p_bCreateElement)
            {
                p_wri.WriteEndElement();
            }
        }//ToXml()
    }//class
    public class JS_Number: JS_Value
    {
        public String Number{get;set;}
        public override string ToString()
        {
            return Number;
        }
        
        public override void ToXml(XmlWriter p_wri, bool p_bCreateElement, String p_strElementName)
        {
            String strEleName=XmlHelper.ToValidXmlName(String.IsNullOrEmpty(p_strElementName)? "Value" : p_strElementName);
            if (p_bCreateElement)
            {
                p_wri.WriteStartElement_auto(strEleName);
            }
            p_wri.WriteAttributeString("type", "number");
            p_wri.WriteString(Number);
            if (p_bCreateElement)
            {
                p_wri.WriteEndElement();
            }
        }
    }
    public class JS_Object: JS_Value
    {
        private Dictionary<String, JS_Value> m_properties=new Dictionary<String, JS_Value> ();
        public Dictionary<String, JS_Value> Properties{
            get{
                return m_properties;
            }
        }
        public override string ToString()
        {
            if(m_properties.Count<=0)
                return "{}";
            else
                return "{" + m_properties.Select(x=>"\"" + x.Key + "\":" + x.Value.ToString())
                    .Aggregate((x,y)=> x + ",\r\n" +y ) +"}";
        }
        
        public override void ToXml(XmlWriter p_wri, bool p_bCreateElement, String p_strElementName)
        {
            String strEleName=XmlHelper.ToValidXmlName(String.IsNullOrEmpty(p_strElementName)? "Value" : p_strElementName);
            if (p_bCreateElement)
            {
                p_wri.WriteStartElement_auto(strEleName);
            }
            p_wri.WriteAttributeString("type", "object");
            foreach (String properName in m_properties.Keys) {
                m_properties[properName].ToXml(p_wri, true, properName);
            }
            if (p_bCreateElement)
            {
                p_wri.WriteEndElement();
            }
        }
    }//class JS_Obj
    public class JS_Array : JS_Value
    {
        private List<JS_Value> m_elements=new List<JS_Value>();
        public List<JS_Value> Elements{
            get{
                return m_elements;
            }
        }
        public override string ToString()
        {
            if(m_elements.Count<=0)
                return "[]";
            else
                return "[" + m_elements.Select(x=>x.ToString()).Aggregate((x,y)=> x + ",\r\n" +y ) +"]";
        }

        
        public override void ToXml(XmlWriter p_wri, bool p_bCreateElement, String p_strElementName)
        {
            String strEleName="Value";
            if (p_bCreateElement)
            {
                p_wri.WriteStartElement_auto(strEleName);
            }
            p_wri.WriteAttributeString("type", "array");
            foreach (JS_Value element in m_elements) {
                element.ToXml(p_wri, true, p_strElementName);
            }
            if (p_bCreateElement)
            {
                p_wri.WriteEndElement();
            }
        }
    }
    public enum enumJSConst{
        eTrue, eFalse,eNull
    }
    public class JS_Const : JS_Value
    {
        public JS_Const(enumJSConst val){ m_value = val;}
        private enumJSConst m_value;
        public enumJSConst Value{get{return m_value;}}
        
        public override string ToString()
        {
            return m_value.ToString().Substring(1).ToLower();
        }
        public override void ToXml(XmlWriter p_wri, bool p_bCreateElement, String p_strElementName)
        {
            String strEleName=XmlHelper.ToValidXmlName(String.IsNullOrEmpty(p_strElementName)? "Value" : p_strElementName);
            if (p_bCreateElement)
            {
                p_wri.WriteStartElement_auto(strEleName);
            }
            p_wri.WriteAttributeString("type", "const");
            p_wri.WriteString(ToString());
            if (p_bCreateElement)
            {
                p_wri.WriteEndElement();
            }
        }

        
        public static JS_Const True = new JS_Const(enumJSConst.eTrue);
        public static JS_Const False = new JS_Const(enumJSConst.eFalse);
        public static JS_Const Null = new JS_Const(enumJSConst.eNull);
        
    }
    public class JsonDecoder
    {
        public static JS_Value Decode(String p_stream)
        {
            if (String.IsNullOrWhiteSpace(p_stream))
                return null;
            else
            {
                String s=p_stream.Trim();
                int nPos=0;
                JS_Value v= GetValue(s, ref nPos);
                if (nPos == s.Length)
                    return v;
                else
                    throw Error.InvalidJsonStream;
            }
        }
        private static char NextChar(String p_stream, ref int p_currentPos)
        {
            if (p_currentPos>=p_stream.Length)
                throw Error.InvalidJsonStream;
            return p_stream[p_currentPos++];
        }
        private static void SkipSpaces(String p_stream, ref int p_currentPos)
        {
            while (p_currentPos<p_stream.Length
                   && (Char.IsWhiteSpace(p_stream[p_currentPos])
                      /* || Char.IsControl(p_stream[p_currentPos])*/
                      )
                  )
            {
                p_currentPos++;
            }//while
            
        }
        private static char PeekChar(String p_stream, int p_currentPos)
        {
            if (p_currentPos>=p_stream.Length)
                throw Error.InvalidJsonStream;
            return p_stream[p_currentPos];
        }
        public static JS_Value GetValue(String p_stream, ref int p_currentPos)
        {
            JS_Value newValue=GetConst(p_stream, ref p_currentPos);
            if (null == newValue)
                newValue = GetString(p_stream, ref p_currentPos);
            if (null == newValue)
                newValue = GetNumber(p_stream, ref p_currentPos);
            if (null == newValue)
                newValue = GetObject(p_stream, ref p_currentPos);
            if (null == newValue)
                newValue = GetArray(p_stream, ref p_currentPos);
            
            if(null == newValue)
                throw Error.InvalidJsonStream;
            return newValue;
        }
        public static JS_Number GetNumber(String p_stream, ref int p_currentPos)
        {
              int nLen = p_stream.Length;
              if (p_currentPos>=nLen)
                  return null;
            String strFraction=@"\.[0-9]+";
            String strExposion=@"[eE][+-]?[0-9]+";
            String strPattern=@"^(\-)?[1-9][0-9]*(" + strFraction +")?(" + strExposion + ")?";
//            if(p_stream.Substring(p_currentPos).StartsWith("500"))
//                Console.WriteLine("Here");
            Regex rex=new Regex(strPattern);
            Match m= rex.Match(p_stream.Substring(p_currentPos));
            if (!m.Success) {
                /*m = Regex.Match(p_stream.Substring(p_currentPos), strPattern);
                m = Regex.Match(p_stream.Substring(p_currentPos), @"^-?[1-9][0-9]*");
                m = Regex.Match(p_stream.Substring(p_currentPos), @"^\-?[1-9][0-9]*");
                m = Regex.Match(p_stream.Substring(p_currentPos), @"^(-)?[1-9][0-9]*");
                m = Regex.Match(p_stream.Substring(p_currentPos), @"^(\-)?[1-9][0-9]*");
                */
                return null;
            }
            JS_Number result=new JS_Number();
            result.Number = p_stream.Substring(p_currentPos, m.Groups[0].Length);
            p_currentPos += m.Groups[0].Length;
            return result;
        }
        public static JS_Const GetConst(String p_stream, ref int p_currentPos)
        {
              int nLen = p_stream.Length;
              if (p_currentPos>=nLen)
                  return null;
              string temp=p_stream.Substring(p_currentPos);
              if (temp.StartsWith("true",    StringComparison.CurrentCultureIgnoreCase))
              {
                  p_currentPos+=4;
                  return JS_Const.True;
              }
              if (temp.StartsWith("false",    StringComparison.CurrentCultureIgnoreCase))
              {
                  p_currentPos+=5;
                  return JS_Const.False;
              }
              if (temp.StartsWith("null",    StringComparison.CurrentCultureIgnoreCase))
              {
                  p_currentPos+=4;
                  return JS_Const.Null;
              }
              return null;
        }
        public static JS_Array GetArray(String p_stream, ref int p_currentPos)
        {
              int nLen = p_stream.Length;
              if (p_currentPos>=nLen)
                  return null;
              int nCurrent=p_currentPos;
              if (PeekChar(p_stream, nCurrent) != '[')
                  return null;
              nCurrent++;
              JS_Array result=new JS_Array();
              SkipSpaces(p_stream, ref nCurrent);
              while(nCurrent<=nLen)
              {
                  int c=PeekChar(p_stream,nCurrent);
                  if (c==']')
                  {
                      nCurrent++;
                      break;
                  }
                  bool noMorePairs=false;
                  while(!noMorePairs)
                  {
                      JS_Value propertyValue=GetValue(p_stream, ref nCurrent);
                      result.Elements.Add(propertyValue);
                      SkipSpaces(p_stream, ref nCurrent);
                      if (PeekChar(p_stream, nCurrent) != ',')
                          noMorePairs=true;
                      else
                      {
                          nCurrent++;
                          SkipSpaces(p_stream, ref nCurrent);
                      }
                  }//inner while
              }//outter while
            p_currentPos=nCurrent;
            return result;
        }
        public static JS_Object GetObject(String p_stream, ref int p_currentPos)
        {
              int nLen = p_stream.Length;
              if (p_currentPos>=nLen)
                  return null;
              int nCurrent=p_currentPos;
              if (PeekChar(p_stream, nCurrent) != '{')
                  return null;
              nCurrent++;
              JS_Object result=new JS_Object();
              SkipSpaces(p_stream, ref nCurrent);
              while(nCurrent<=nLen)
              {
                  int c=PeekChar(p_stream,nCurrent);
                  if (c=='}')
                  {
                      nCurrent++;
                      break;
                  }
                  bool noMorePairs=false;
                  while(!noMorePairs)
                  {
                      JS_String propertyName=GetString(p_stream, ref nCurrent);
                      SkipSpaces(p_stream, ref nCurrent);
                      Char c1 =NextChar(p_stream,ref nCurrent);
                      if (c1!=':')
                          throw Error.InvalidJsonStream;
                      SkipSpaces(p_stream, ref nCurrent);
                      JS_Value propertyValue=GetValue(p_stream, ref nCurrent);
                      result.Properties.Add(propertyName.Value, propertyValue);
                      SkipSpaces(p_stream, ref nCurrent);
                      if (PeekChar(p_stream, nCurrent) != ',')
                          noMorePairs=true;
                      else
                      {
                          nCurrent++;
                          SkipSpaces(p_stream, ref nCurrent);
                      }
                  }//inner while
              }//outter while
            p_currentPos=nCurrent;  
            return result;
        }
        public static JS_String GetString(String p_stream, ref int p_currentPos)
        {
          int nLen = p_stream.Length;
          if (p_currentPos>=nLen)
              return null;
          JS_String result=new JS_String();
          int nCurrent=p_currentPos;
          if (PeekChar(p_stream, nCurrent) != '"')
              return null;
          nCurrent++;
          StringBuilder bld=new StringBuilder();
          while(nCurrent<=nLen)
          {
              Char c=p_stream[nCurrent++];
              if (c=='"')
                  break;
              if (c != '\\')
              {
                  bld.Append(c);
                  continue;
              }
              c = NextChar(p_stream, ref nCurrent);
              if (c=='"')
                  bld.Append('"');
              else if (c == '\\')
                  bld.Append('\\');
              else if (c == '/')
                  bld.Append('/');
              else if (c == 'b')
                  bld.Append('\b');
              else if (c == 't')
                  bld.Append('\t');
              else if (c == 'r')
                  bld.Append('\r');
              else if (c == 'n')
                  bld.Append('\n');
              else if (c == 'f')
                  bld.Append('\f');
              else if (c == 'u')
              {
                  char[] code=new Char[4];
                  code[0]=NextChar(p_stream, ref nCurrent);
                  code[1]=NextChar(p_stream, ref nCurrent);
                  code[2]=NextChar(p_stream, ref nCurrent);
                  code[3]=NextChar(p_stream, ref nCurrent);
                  int nCodePoint=Int32.Parse(code.ToString(), NumberStyles.HexNumber);
                  bld.Append((char)nCodePoint);
              }
          }//while()
          result.Value = bld.ToString();
          result.RawValue = p_stream.Substring(p_currentPos, nCurrent-p_currentPos);
          p_currentPos=nCurrent;
          return result;
        }
        
    } //class JsonDecoder
    public static class Error{
        public static Exception InvalidJsonStream
        {
            get
            {
                return new Exception("Invalid Json Stream");
            }
        }
    }//class Error
}

 

这个只是给你一个方向,如果要用的话,需要修改符合自己的业务规则或者适合自己的使用。

 

出处:https://www.cnblogs.com/sliencer/archive/2013/06/25/3155768.html

posted on 2018-02-03 02:28  jack_Meng  阅读(3100)  评论(0编辑  收藏  举报

导航