views:

81

answers:

2

I would like to keep a custom configuration file for my app and JSON seems like an appropriate format*.

I know that there are JSON libraries for .NET, but I couldn't find a good comparative review of them. Also, my app needs to run on mono, so it's even harder to find out which library to use.

Here's what I've found:

I remember reading that there is a built-in way to (de)serialize JSON as well, but I don't recall what it is.

What library would be easiest to use in mono on linux? Speed isn't critical, as the data will be small.

*Since the app runs on a headless linux box, I need to use the command line and would like to keep typing down to a minimum, so I ruled out XML. Also, I couldn't find any library to work with INF files, I'm not familiar with standard linux config file formats, and JSON is powerful.

+1  A: 

The DataContractJsonSerializer can handle JSON serialization but it's not as powerful as some of the libraries for example it has no Parse method.

This might be a way to do it without libraries as I beleive Mono has implemented this class.

To get more readable JSON markup your class with attributes:

[DataContract]
public class SomeJsonyThing
{
    [DataMember(Name="my_element")]
    public string MyElement { get; set; }

    [DataMember(Name="my_nested_thing")]
    public object MyNestedThing { get; set;}
}
Rob Stevenson-Leggett
In my tests mono 2.8 has indeed implemented this class.
Pat
It looks like DCJS doesn't format the JSON in a very user-readable manner, but it works!
Pat
Try annotating to get better element names. See my edit.
Rob Stevenson-Leggett
A: 

Below is my implementation using the DataContractJsonSerializer. It works in mono 2.8 on windows and ubuntu 9.04 (with mono 2.8 built from source). (And, of course, it works in .NET!) I've implemented some suggestions from Best Practices: Data Contract Versioning . The file is stored in the same folder as the exe (not sure if I did that in the best manner, but it works in win and linux).

using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;

using NLog;

[DataContract]
public class UserSettings : IExtensibleDataObject
{
    ExtensionDataObject IExtensibleDataObject.ExtensionData { get; set; }

    [DataMember]
    public int TestIntProp { get; set; }

    private string _testStringField;
}

public static class SettingsManager
{
    private static Logger _logger = LogManager.GetLogger("SettingsManager");

    private static UserSettings _settings;

    private static readonly string _path =
        Path.Combine(
            Path.GetDirectoryName(
                System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName),
            "settings.json");

    public static UserSettings Settings
    {
        get
        {
            return _settings;
        }
    }

    public static void Load()
    {
        if (string.IsNullOrEmpty(_path))
        {
            _logger.Trace("empty or null path");
            _settings = new UserSettings();
        }
        else
        {
            try
            {
                using (var stream = File.OpenRead(_path))
                {
                    _logger.Trace("opened file");
                    _settings = SerializationExtensions.LoadJson<UserSettings>(stream);
                    _logger.Trace("deserialized file ok");
                }
            }
            catch (Exception e)
            {
                _logger.TraceException("exception", e);
                if (e is InvalidCastException
                    || e is FileNotFoundException
                    || e is SerializationException
                    )
                {
                    _settings = new UserSettings();
                }
                else
                {
                    throw;
                }
            }
        }
    }

    public static void Save()
    {
        if (File.Exists(_path))
        {
            string destFileName = _path + ".bak";
            if (File.Exists(destFileName))
            {
                File.Delete(destFileName);
            }
            File.Move(_path, destFileName);
        }
        using (var stream = File.Open(_path, FileMode.Create))
        {
            Settings.WriteJson(stream);
        }
    }
}

public static class SerializationExtensions
{
    public static T LoadJson<T>(Stream stream) where T : class
    {
        var serializer = new DataContractJsonSerializer(typeof(T));
        object readObject = serializer.ReadObject(stream);
        return (T)readObject;
    }

    public static void WriteJson<T>(this T value, Stream stream) where T : class
    {
        var serializer = new DataContractJsonSerializer(typeof(T));
        serializer.WriteObject(stream, value);
    }
}
Pat