/*
*
* Copyright (c) 2010, Raymond Glover
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Cynosura nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
*/
namespace Cynosura.Base
{
using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.Web.Script.Serialization;
///
/// A helper class for generating object graphs in
/// JavaScript notation. Supports pretty printing.
///
public class JsonHelper
{
public static string Serialize(Object target)
{
return Serialize(target, false);
}
public static string Serialize(Object target, bool prettyPrint)
{
StringBuilder sbSerialized = new StringBuilder();
JavaScriptSerializer js = new JavaScriptSerializer();
js.Serialize(target, sbSerialized);
if(prettyPrint) {
StringBuilder prettyPrintedResult = new StringBuilder();
prettyPrintedResult.EnsureCapacity(sbSerialized.Length);
JsonPrettyPrinter pp = new JsonPrettyPrinter();
pp.PrettyPrint(sbSerialized, prettyPrintedResult);
return prettyPrintedResult.ToString();
} else
return sbSerialized.ToString();
}
}
private enum JsonContextType
{
Object, Array
}
public class JsonPrettyPrinter
{
#region class members
const string Space = " ";
const int DefaultIndent = 0;
const string Indent = Space + Space + Space + Space;
static readonly string NewLine = Environment.NewLine;
static void BuildIndents(int indents, StringBuilder output)
{
indents += DefaultIndent;
for (;indents > 0; indents--)
output.Append(Indent);
}
#endregion
bool inDoubleString = false;
bool inSingleString = false;
bool inVariableAssignment = false;
char prevChar = '\0';
Stack context = new Stack();
bool InString()
{
return inDoubleString || inSingleString;
}
public void PrettyPrint(StringBuilder input, StringBuilder output)
{
if (input == null) throw new ArgumentNullException("input");
if (output == null) throw new ArgumentNullException("output");
int inputLength = input.Length;
char c;
for (int i = 0; i < inputLength; i++) {
c = input[i];
switch (c) {
case '{':
if (!InString()) {
if (inVariableAssignment || (context.Count > 0 && context.Peek() != JsonContextType.Array)) {
output.Append(NewLine);
BuildIndents(context.Count, output);
}
output.Append(c);
context.Push(JsonContextType.Object);
output.Append(NewLine);
BuildIndents(context.Count, output);
} else
output.Append(c);
break;
case '}':
if (!InString()) {
output.Append(NewLine);
context.Pop();
BuildIndents(context.Count, output);
output.Append(c);
} else
output.Append(c);
break;
case '[':
output.Append(c);
if (!InString())
context.Push(JsonContextType.Array);
break;
case ']':
if (!InString()) {
output.Append(c);
context.Pop();
} else
output.Append(c);
break;
case '=':
output.Append(c);
break;
case ',':
output.Append(c);
if (!InString() && context.Peek() != JsonContextType.Array) {
BuildIndents(context.Count, output);
output.Append(NewLine);
BuildIndents(context.Count, output);
inVariableAssignment = false;
}
break;
case '\'':
if (!inDoubleString && prevChar != '\\')
inSingleString = !inSingleString;
output.Append(c);
break;
case ':':
if (!InString()) {
inVariableAssignment = true;
output.Append(Space);
output.Append(c);
output.Append(Space);
} else
output.Append(c);
break;
case '"':
if (!inSingleString && prevChar != '\\')
inDoubleString = !inDoubleString;
output.Append(c);
break;
default:
output.Append(c);
break;
}
prevChar = c;
}
}
}
}