Skip to content

Instantly share code, notes, and snippets.

@codesoda
Last active July 31, 2017 12:29
Show Gist options
  • Save codesoda/914857 to your computer and use it in GitHub Desktop.
Save codesoda/914857 to your computer and use it in GitHub Desktop.
A Simple c# class for creating well formed JSON strings when serializing classes with Json.NET is overkill.
public class JsonBuilder
{
private readonly StringBuilder _sb;
private readonly Stack<bool> _hasPreviousProperties;
private bool RequiresComma { get { return _hasPreviousProperties.Count > 0 && _hasPreviousProperties.Peek(); } }
public JsonBuilder() {
_sb = new StringBuilder();
_hasPreviousProperties = new Stack<bool>();
}
public JsonBuilder WriteObject(string name, Action<JsonBuilder> buildChildren)
{
WriteCommaIf(RequiresComma);
if (_hasPreviousProperties.Count > 0) {
_hasPreviousProperties.Pop();
}
_hasPreviousProperties.Push(false);
_sb.AppendFormat("{0}:{{", name);
buildChildren(this);
_sb.Append("}");
if (_hasPreviousProperties.Count > 0) {
_hasPreviousProperties.Pop();
}
_hasPreviousProperties.Push(true);
return this;
}
public JsonBuilder WriteObject( Action<JsonBuilder> buildChildren )
{
// if object is anonymous don't write comma, the coder should have done it
_sb.Append("{");
if (_hasPreviousProperties.Count > 0) {
_hasPreviousProperties.Pop();
}
_hasPreviousProperties.Push(false);
buildChildren(this);
_sb.Append("}");
return this;
}
public JsonBuilder WritePropertyIf(string name, object value, bool onlyIf) {
if (onlyIf)
return WriteProperty(name, value);
return this;
}
public JsonBuilder WriteProperty(string name, object value)
{
WriteCommaIf(RequiresComma);
_sb.AppendFormat("{0}:", name);
WriteObject(value);
if (_hasPreviousProperties.Count > 0)
_hasPreviousProperties.Pop();
_hasPreviousProperties.Push(true);
return this;
}
public void WriteNull()
{
_sb.Append("null");
}
public void WriteArray(IEnumerable values)
{
_sb.Append("[");
_hasPreviousProperties.Push(false);
foreach (object value in values)
{
WriteCommaIf(RequiresComma);
WriteObject(value);
_hasPreviousProperties.Pop();
_hasPreviousProperties.Push(true);
}
_sb.Append("]");
}
public StringBuilder Raw { get { return _sb; } }
public override string ToString()
{
return _sb.ToString();
}
private void WriteCommaIf(bool ifOnly)
{
if (ifOnly)
WriteComma();
}
public void WriteComma() {
_sb.Append(",");
}
private void WriteObject(object value)
{
if (value == null)
WriteNull();
else if (value is string)
WriteString((string)value);
else if (value is bool)
WriteBoolean((bool)value);
else if (value is int)
WriteInt32((int)value);
else if (value is double)
WriteDouble((double)value);
else if (value is IEnumerable)
WriteArray((IEnumerable)value);
else
_sb.Append(value.ToString()); // ewww
}
private void WriteBoolean(bool value) {
_sb.Append(value.ToString().ToLower());
}
private void WriteString(string value)
{
_sb.AppendFormat("\"{0}\"", value.Replace(@"\", "")
.Replace("\"", "\\\"")
.Replace("\r","\\r")
.Replace("\n","\\n")
.Replace("\t","\\t")
.Replace("/","\\/")
.Replace("\b","\\b")
.Replace("\f","\\f"));
}
private void WriteInt32(int value) {
_sb.Append(value);
}
private void WriteDouble(double value) {
_sb.Append(value);
}
}
@jitcoder
Copy link

jitcoder commented Jul 3, 2015

you're not escaping any of the characters that require escaping; such as \r
see http://json.org/ (white box on the right lists characters that should be escaped)

@jitcoder
Copy link

jitcoder commented Jul 3, 2015

    private void WriteString(string value)
    {
        _sb.AppendFormat("\"{0}\"", value.Replace(@"\", "")
                                         .Replace("\"", "\\\"")
                                         .Replace("\r","\\r")
                                         .Replace("\n","\\n")
                                         .Replace("\t","\\t")
                                         .Replace("/","\\/")
                                         .Replace("\b","\\b")
                                         .Replace("\f","\\f"));
    }

Only thing missing here is unicode character encoding (UTF-16?)

@codesoda
Copy link
Author

Thanks @jitcoder, will update

@sundeepsd
Copy link

Where is BuildChildren method

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment