using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ranslant.JSON.Linq;
namespace DemoApp
{
class Program
{
static void Main(string[] args)
{
EncodingTests();
// uncomment the line below to get the exception
//Writetest2_MustTriggerException("testfail.json"); // won't trigger an exception: code is commented out. Remove the comment marker to get the exception
WriteTest1_MustSucceed("test1.json");
ReadTest_MustSucceed("test1.json", true);
// uncomment the line below to get the exception
//ReadTest_mustFail("testfail.json"); // failed as expected, until the json content was fixed in the file
WriteReadTest_MustSucceed("WRtest.json");
}
private static void EncodingTests()
{
// write the data
WriteJsonDataWithByteOrderMark("simpson_ascii.json", new ASCIIEncoding());
WriteJsonDataWithByteOrderMark("simpson_utf8.json", new UTF8Encoding(true)); // use new UTF8Encoding(true) to get the UTF-8 3bytes ByteOrderMark
WriteJsonDataWithByteOrderMark("simpson_utf16LE.json", new UnicodeEncoding(false, true));
WriteJsonDataWithByteOrderMark("simpson_utf16BE.json", new UnicodeEncoding(true, true));
// read the data
JDocument doc01 = JDocument.Load("simpson_ascii.json", null);
JDocument doc02 = JDocument.Load("simpson_utf8.json", null);
JDocument doc03 = JDocument.Load("simpson_utf16LE.json", null);
JDocument doc04 = JDocument.Load("simpson_utf16BE.json", null);
JDocument doc1 = JDocument.Load("simpson_ascii.json", new ASCIIEncoding());
JDocument doc2 = JDocument.Load("simpson_utf8.json", new UTF8Encoding());
JDocument doc3 = JDocument.Load("simpson_utf16LE.json", new UnicodeEncoding());
//JDocument doc31 = JDocument.Load("simpson_utf16BE.json", new UnicodeEncoding()); // fails as expected
//JDocument doc32 = JDocument.Load("simpson_utf16BE.json", new UnicodeEncoding(false, true, true)); // fails as expected
JDocument doc33 = JDocument.Load("simpson_utf16BE.json", new UnicodeEncoding(true, true, true));
JDocument doc4 = JDocument.Load("simpson_ascii.json", new UTF8Encoding()); // works, this is expected though, since all ascii characters are also encoded over 8 bits. They are therefore properly recognized.
//JDocument doc41 = JDocument.Load("simpson_ascii.json", new UnicodeEncoding()); // fails as expected
//JDocument doc5 = JDocument.Load("simpson_utf8.json", new ASCIIEncoding()); // fails as expected
//JDocument doc36 = JDocument.Load("simpson_utf16LE.json", new ASCIIEncoding()); // fails as expected
//JDocument doc37 = JDocument.Load("simpson_utf16LE.json", new UTF8Encoding()); // fails as expected
}
private static void WriteJsonDataWithByteOrderMark(string filename, Encoding encoding)
{
// example of JDocument written only through the constructor:
new JDocument(
new JObjectMember("D'oh",
new JObject(
new JObjectMember("First Name", new JString("Homer")),
new JObjectMember("Family Name", new JString("Simpson")),
new JObjectMember("Is Fat?", new JTrue()),
new JObjectMember("Children",
new JArray
(
new JString("Bart"),
new JString("Lisa"),
new JString("Maggie")
)
)
)
),
new JObjectMember("never gets older",
new JObject(
new JObjectMember("First Name", new JString("Bart")),
new JObjectMember("Family Name", new JString("Simpson"))
)
)
).Save(filename, encoding, true);
}
private static void WriteReadTest_MustSucceed(string filename)
{
if (filename.Length == 0)
return;
JDocument docW = WriteTest1_MustSucceed(filename);
JDocument docR = ReadTest_MustSucceed(filename, false);
//todo: compare docW and DocR
}
private static void ReadTest_mustFail(string filename)
{
if (filename.Length == 0)
return;
// the JSON data provided has to be voluntarily faulty and therefore allowed to check that an exception is properly thrown
// I took test1.json, renamed it to testfail.json and modified it to make it faulty by removing tokens or adding wrong content for instance
JDocument doc = JDocument.Load(filename);
}
private static JDocument ReadTest_MustSucceed(string filename, bool consoleOutput)
{
if (filename.Length == 0)
return null;
// first, load the document
JDocument jDoc = JDocument.Load(filename);
if (consoleOutput)
{
// then, you can use LINQ to parse the document
var q = from o in jDoc.GetMembers()
select o;
foreach (var o in q)
{
// you can filter the values using their type
if (o.Value is JString || o.Value is JNumber)
Console.WriteLine("string or number: {0} : {1}", o.Name, o.Value.ToString(0));
else
if (o.Value is JFalse || o.Value is JTrue || o.Value is JNull)
Console.WriteLine("true, false or null: {0} : {1}", o.Name, o.Value.ToString(0));
// you can filter the values using their type
if (o.Value is JObject)
{
JObject obj = o.Value as JObject;
Console.WriteLine("---(OBJECT)---\r\n\tobject name:{0} ({1} members)", o.Name, obj.Count);
Console.WriteLine("\t---All members (per member name, with type):");
var names = from name in obj.GetNames()
select name;
foreach (var name in names)
{
// you can get an object with its name
IJValue value = obj[name];
if (value is JString || value is JNumber || value is JFalse || value is JTrue || value is JNull)
Console.WriteLine("\t{0} ({1}) : {2}", name, value.GetType().ToString(), value.ToString(0));
else
Console.WriteLine("\t{0} ({1})", name, value.GetType().ToString());
}
Console.WriteLine("\t---All values (without the member name):");
var values = from value in obj.GetValues()
select value;
foreach (var value in values)
{
Console.WriteLine("\t{0}", value.ToString(1));
}
Console.WriteLine("\t---All members (with GetMembers()):");
var members = from member in obj.GetMembers()
select member;
foreach (var member in members)
{
Console.WriteLine("\t{0} : {1}", member.Name, member.Value.ToString(0));
}
}
if (o.Value is JArray)
{
JArray jarray = o.Value as JArray;
Console.WriteLine("---(ARRAY)---\r\n\tarray name:{0} ({1} members)", o.Name, jarray.Count);
// you can use GetValues()
foreach (IJValue val in jarray.GetValues())
{
Console.WriteLine("\t-----element type {0}", val.GetType().ToString());
}
// ... or an index: jarray[i]
for (int i = 0; i < jarray.Count; i++)
{
Console.WriteLine("\t-----element type {0}", jarray[i].GetType().ToString());
}
}
}
Console.WriteLine();
Console.WriteLine("Press ENTER to continue...");
Console.ReadLine();
}
return jDoc;
}
private static void Writetest2_MustTriggerException(string filename)
{
if (filename.Length == 0)
return;
// all below should fail
/**/
// remove or put back the space between /** and the following / to switch the comments on / off
JArray arrTest = new JArray(
new JNumber("+"), //fails as expected: we need a number
new JNumber("abcd"), //fails as expected: we need a number
new JNumber(""), //fails as expected: we need a number
new JNumber("123,654"), // fails as expected: the decimal separator is '.'
new JNumber("0xAB"), // fails as expected: no hexadecimal
new JNumber("0145"), // fails as expected: no octal
new JNumber("0123.123e456"), // fails as expected: if the number begins with 0, the next char must be '.'
new JNumber("+12"), // fails as expected: number begins with digit or -
new JNumber(".5"), // fails as expected: number begins with digit or -
new JNumber("6."), // fails as expected: decimal separator without fractional part
new JNumber("6,"), // fails as expected: decimal separator not '.' and fractional part missing
new JNumber("6 "), // fails as expected: no spaces after the number
new JNumber(" 6"), // fails as expected: number begins with digit or -
new JNumber("0x45") // fails as expected: no hexadecimal
);
JDocument doc1 = new JDocument();
doc1.Add("1", new JString(@"\a")); // fails as expected: \a is not allowed
doc1.Add("0", new JString(@"\n\test\\""me:{}")); // fails as expected: \\"" will be read as
doc1.Add("1", new JNull());
doc1.Add("1", new JString(@"")); //fails as expected: name "1" is used twice
doc1.Add("2", new JString(@"\u1")); //fails as expected: \u should be followed by four hexadecimal digits
doc1.Add("3", new JString(@"\u123G")); //fails as expected: \u should be followed by four hexadecimal digits
//*/
}
private static JDocument WriteTest1_MustSucceed(string filename)
{
if (filename.Length == 0)
return null;
// you can create an empty object and add values
JObject obj = new JObject();
obj.Add("_number", new JNumber(-3.14));
obj.Add("_true", new JTrue()); // notice the use of JTrue
obj.Add("_null", new JNull()); // notice the use of JNull
// you can also add the values directly, thanks to JObjectMember
JObject homer = new JObject(
new JObjectMember("First Name", new JString("Homer")),
new JObjectMember("Family Name", new JString("Simpson")),
new JObjectMember("Is Yellow?", new JTrue()), // notice the use of JTrue
new JObjectMember("Is Blue?", new JFalse()) // notice the use of JFalse
);
// you can create an empty array and add values
JArray arr = new JArray();
// ... either only one value
arr.Add(new JNumber("-15.64"));
// ... or more than one at once
// Notice that prefixing your strings with @ will help keeping them be valid JSON strings
arr.Add(new JString(@"Unicode: \u12A0"),
new JString(@"\n\test\""me:{}"), // this string is valid because
// 1. \test is seen as \t + est
// 2. \"" will be checked as \"
new JString("\\n\\test\\\"me:{}"), // same string, without the prefix @
new JString(@"\\test"), // how to get the Json string \\test
new JString("\\\""),
new JString(@"\\"),
homer); // we added an object in the array :)
// or you can add the value directly
JArray otherArray = new JArray(
new JString("test2"),
new JString(string.Empty),
new JNull()); // notice the use of JNull
// ... you can still add values
otherArray.Add(obj);
// here some valid numbers
JArray arrTest = new JArray(
new JNumber("-0.3"),
new JNumber("12"),
new JNumber("0"),
new JNumber("5"),
new JNumber("12345"),
new JNumber("3.45"),
new JNumber("12.35"),
new JNumber("54e-5"),
new JNumber("12.54E+45"),
new JNumber("1.5e-8"),
new JNumber("12345.6789"),
new JNumber("0.987"),
new JNumber(4.16e-8)
);
// JDocument is a JObject itself, therefore we have the same two possibilities:
// 1. add object members in the JDocument constructor
JDocument doc = new JDocument(
new JObjectMember("_false", new JFalse()),
new JObjectMember("_false2", new JFalse())
); // the same name cannot be used twice!
// 2. add object members with Add()
// Add() has two forms:
// 1. with JObjectMember
// you can give one
doc.Add(new JObjectMember("_Father Of the Year", homer));
// or more
doc.Add(
new JObjectMember("_array", arr),
new JObjectMember("_string1", new JString("string1")),
new JObjectMember("_number2", new JNumber("-3.14"))
);
// 2. directly give the name and the value
doc.Add("_otherArray", otherArray);
doc.Add("_obj", obj);
doc.Save(filename);
return doc;
}
}
}