##// END OF EJS Templates
Added Skip method to JSON parser to skip contents of the current node
Added Skip method to JSON parser to skip contents of the current node

File last commit:

r55:c0bf853aa04f default
r62:62b440d46313 default
Show More
JSONWriter.cs
227 lines | 7.1 KiB | text/x-csharp | CSharpLexer
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Implab.JSON {
public class JSONWriter {
struct Context {
public bool needComma;
public JSONElementContext element;
}
Stack<Context> m_contextStack = new Stack<Context>();
Context m_context;
TextWriter m_writer;
bool m_indent;
static readonly char [] _escapeBKS,
_escapeFWD,
_escapeCR,
_escapeNL,
_escapeTAB,
_escapeSLASH,
_escapeBSLASH,
_escapeQ;
static JSONWriter() {
_escapeBKS = "\\b".ToCharArray();
_escapeFWD = "\\f".ToCharArray();
_escapeCR = "\\r".ToCharArray();
_escapeNL = "\\n".ToCharArray();
_escapeTAB = "\\t".ToCharArray();
_escapeBSLASH = "\\\\".ToCharArray();
_escapeSLASH = "\\/".ToCharArray();
_escapeQ = "\\\"".ToCharArray();
}
public JSONWriter(TextWriter writer) {
Safe.ArgumentNotNull(writer, "writer");
m_writer = writer;
}
void WriteMemberName(string name) {
Safe.ArgumentNotEmpty(name, "name");
if (m_context.element != JSONElementContext.Object)
OperationNotApplicable("WriteMember");
if (m_context.needComma)
m_writer.Write(", ");
// TODO indent
m_context.needComma = true;
Write(name);
m_writer.Write(" : ");
}
public void WriteValue(string name, string value) {
WriteMemberName(name);
Write(value);
}
public void WriteValue(string name, bool value) {
WriteMemberName(name);
Write(value);
}
public void WriteValue(string name, double value) {
WriteMemberName(name);
Write(value);
}
public void WriteValue(string value) {
if (m_context.element != JSONElementContext.Array)
OperationNotApplicable("WriteValue");
if (m_context.needComma)
m_writer.Write(", ");
m_context.needComma = true;
Write(value);
}
public void WriteValue(bool value) {
if (m_context.element != JSONElementContext.Array)
OperationNotApplicable("WriteValue");
if (m_context.needComma)
m_writer.Write(", ");
m_context.needComma = true;
Write(value);
}
public void WriteValue(double value) {
if (m_context.element != JSONElementContext.Array)
OperationNotApplicable("WriteValue");
if (m_context.needComma)
m_writer.Write(", ");
m_context.needComma = true;
Write(value);
}
public void BeginObject() {
if (m_context.element != JSONElementContext.None && m_context.element != JSONElementContext.Array)
OperationNotApplicable("BeginObject");
if (m_context.needComma)
m_writer.Write(", ");
m_context.needComma = true;
m_contextStack.Push(m_context);
m_context = new Context { element = JSONElementContext.Object, needComma = false };
m_writer.Write("{ ");
}
public void BeginObject(string name) {
WriteMemberName(name);
m_contextStack.Push(m_context);
m_context = new Context { element = JSONElementContext.Object, needComma = false };
m_writer.Write("{ ");
}
public void EndObject() {
if (m_context.element != JSONElementContext.Object)
OperationNotApplicable("EndArray");
m_writer.Write(" }");
m_context = m_contextStack.Pop();
}
public void BeginArray() {
if (m_context.element != JSONElementContext.None && m_context.element != JSONElementContext.Array)
throw new InvalidOperationException();
if (m_context.needComma)
m_writer.Write(", ");
m_context.needComma = true;
m_contextStack.Push(m_context);
m_context = new Context { element = JSONElementContext.Array, needComma = false };
m_writer.Write("[ ");
}
public void BeginArray(string name) {
WriteMemberName(name);
m_contextStack.Push(m_context);
m_context = new Context { element = JSONElementContext.Array, needComma = false };
m_writer.Write("[ ");
}
public void EndArray() {
if (m_context.element != JSONElementContext.Array)
OperationNotApplicable("EndArray");
m_writer.Write(" ]");
m_context = m_contextStack.Pop();
}
void Write(bool value) {
m_writer.Write(value ? "true" : "false");
}
void Write(string value) {
if (value == null)
m_writer.Write("null");
var chars = value.ToCharArray();
m_writer.Write('"');
for (int i = 0; i < chars.Length; i++) {
var ch = chars[i];
switch (ch) {
case '\b':
m_writer.Write(_escapeBKS);
break;
case '\f':
m_writer.Write(_escapeFWD);
break;
case '\r':
m_writer.Write(_escapeCR);
break;
case '\n':
m_writer.Write(_escapeNL);
break;
case '\t':
m_writer.Write(_escapeTAB);
break;
case '\\':
m_writer.Write(_escapeBSLASH);
break;
case '/':
m_writer.Write(_escapeSLASH);
break;
case '"':
m_writer.Write(_escapeQ);
break;
default:
if (ch < 0x20) {
m_writer.Write("\\u00{0:x2}",(int)ch);
} else {
m_writer.Write(ch);
}
break;
}
}
m_writer.Write('"');
}
void Write(double value) {
m_writer.Write(value);
}
void OperationNotApplicable(string opName) {
throw new InvalidOperationException(String.Format("The operation '{0}' isn't applicable in the context of '{1}'", opName, m_context.element ));
}
}
}