Skip to content
Snippets Groups Projects
JSONManager.cs 9.97 KiB
Newer Older
  • Learn to ignore specific revisions
  • using System.Collections.Generic;
    using System.Reflection;
    using System.IO;
    using System;
    using System.Linq;
    
    using Newtonsoft.Json;
    
    using JsonSubTypes;
    
    using System.Collections;
    using UnityEngine;
    
    using Newtonsoft.Json.Linq;
    
    
    public class MMTURICollection
    {
        public string Point = "http://mathhub.info/MitM/core/geometry?3DGeometry?point";
        public string Tuple = "http://gl.mathhub.info/MMT/LFX/Sigma?Symbols?Tuple";
    
        public string LineType = "http://mathhub.info/MitM/core/geometry?Geometry/Common?line_type";
        public string LineOf = "http://mathhub.info/MitM/core/geometry?Geometry/Common?lineOf";
        public string OnLine = "http://mathhub.info/MitM/core/geometry?Geometry/Common?onLine";
    
        public string Ded = "http://mathhub.info/MitM/Foundation?Logic?ded";
        public string Eq = "http://mathhub.info/MitM/Foundation?Logic?eq";
    
        public string Metric = "http://mathhub.info/MitM/core/geometry?Geometry/Common?metric";
        public string Angle = "http://mathhub.info/MitM/core/geometry?Geometry/Common?angle_between";
    
        public string Sketch = "http://mathhub.info/MitM/Foundation?InformalProofs?proofsketch";
    
        public string RealLit = "http://mathhub.info/MitM/Foundation?RealLiterals?real_lit";
    
    public static class JSONManager 
    {
    
        //could init the strings of MMTURIs with JSON or other settings file instead
        public static MMTURICollection MMTURIs = new MMTURICollection();
    
    
        public class URI
        {
            public string uri;
    
            public URI(string uri)
            {
                this.uri = uri;
            }
        }
    
        [JsonConverter(typeof(JsonSubtypes), "kind")]
        public class MMTTerm
        {
            string kind;
        }
    
        public class OMA : MMTTerm
        {
            public MMTTerm applicant;
            public List<MMTTerm> arguments;
            public string kind = "OMA";
            public OMA(MMTTerm applicant, List<MMTTerm> arguments)
            {
                this.applicant = applicant;
                this.arguments = arguments;
            }
        }
    
        public class OMS : MMTTerm
        {
            public string uri;
            public string kind = "OMS";
    
    
            public OMS(string uri)
            {
                this.uri = uri;
            }
        }
    
        public class OMSTR : MMTTerm
        {
            [JsonProperty("float")]
            public string s;
            public string kind = "OMSTR";
    
            public OMSTR(string s)
    
                this.s = s;
    
            }
        }
    
        public class OMF : MMTTerm
        {
            [JsonProperty("float")]
    
            public float f;
    
            public string kind = "OMF";
    
            public OMF(float f)
            {
    
                this.f = f;
    
            }
        }
    
        public class MMTDeclaration
    
        {
            public static MMTDeclaration FromJson(string json)
            {
                MMTDeclaration mmtDecl = JsonConvert.DeserializeObject<MMTDeclaration>(json);
                return mmtDecl;
            }
            public static string ToJson(MMTDeclaration mmtDecl)
            {
                string json = JsonConvert.SerializeObject(mmtDecl);
                return json;
            }
        }
    
    
        /**
         * MMTSymbolDeclaration: Class for facts without values, e.g. Points
    
        public class MMTSymbolDeclaration : MMTDeclaration
    
            public string kind = "general";
    
            public string label;
            public MMTTerm tp;
            public MMTTerm df;
    
            /**
             * Constructor used for sending new declarations to mmt
             */
    
            public MMTSymbolDeclaration(string label, MMTTerm tp, MMTTerm df)
    
            {
                this.label = label;
                this.tp = tp;
                this.df = df;
            }
    
        /**
         * MMTValueDeclaration: Class for facts with values, e.g. Distances or Angles
    
        public class MMTValueDeclaration : MMTDeclaration
    
            public string kind = "veq";
    
            public string label;
            public MMTTerm lhs;
    
            public MMTTerm valueTp;
            public MMTTerm value;
    
            /**
             * Constructor used for sending new declarations to mmt
             */
    
            public MMTValueDeclaration(string label, MMTTerm lhs, MMTTerm valueTp, MMTTerm value)
    
            {
                this.label = label;
                this.lhs = lhs;
    
                this.valueTp = valueTp;
                this.value = value;
    
    
        // TODO? /// <para>If there are public properties/variables that you do not want written to the file, decorate them with the [JsonIgnore] attribute.</para>
    
        /// <summary>
        /// Writes the given object instance to a Json file, recursively to set depth, including all members.
        /// <para>Object type must have a parameterless constructor.</para>
        /// <para>Only All properties and variables will be written to the file. These can be any type though, even other non-abstract classes.</para>
        /// </summary>
        /// <param name="filePath">The file path to write the object instance to.</param>
        /// <param name="objectToWrite">The object instance to write to the file.</param>
        /// <param name="max_depth">The depth recursion will occur. Default = 0.</param>
        public static void WriteToJsonFile(string filePath, object objectToWrite, int max_depth = 0)
        {
            int current_depth = 0;
    
            // This tells your serializer that multiple references are okay.
            var settings = new JsonSerializerSettings();
            settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
    
            BindingFlags bindFlags =
                BindingFlags.Instance |
                BindingFlags.Public |
                BindingFlags.NonPublic |
                BindingFlags.Static;
    
            TextWriter writer = null;
            try
            {
                string payload = RecursiveStep(objectToWrite);
                writer = new StreamWriter(filePath);
                writer.Write(payload);
            }
            finally
            {
                if (writer != null)
                    writer.Close();
            }
    
    
            // ======= local methods ======= 
            // TODO? more stable depths (see next todo)
            // TODO? respect IgnoreJson tags
    
            string RecursiveStep<S>(S objectToWrite) where S : new()
            {
                string json;
    
                if (current_depth >= max_depth 
                 || Type.GetTypeCode(objectToWrite.GetType()) != TypeCode.Object
                 || objectToWrite == null)
                    json = JsonConvert.SerializeObject(objectToWrite, settings/*, new JsonInheritenceConverter<object>()*/);
                else
                {
                    current_depth++;
                    json = IntrusiveRecursiveJsonGenerator(objectToWrite);
                    current_depth--;
                }
    
                return json;
            }
    
            string IntrusiveRecursiveJsonGenerator<S>(S objectToWrite) where S : new()
            // private convention? more like private suggestion!
            {
                bool is_enum = IsEnumerableType(objectToWrite.GetType());
    
                string json = is_enum ? "[" : "{";
                foreach (object field in is_enum ? (objectToWrite as IEnumerable) : objectToWrite.GetType().GetFields(bindFlags))
                {
                    object not_so_private;
                    if (is_enum)
                    {
                        not_so_private = field;
                    }
                    else
                    {
                        not_so_private = ((FieldInfo)field).GetValue(objectToWrite);
                        json += ((FieldInfo)field).Name + ":";
                    }
    
                    json += RecursiveStep(not_so_private);
    
                    json += ",";
                }
                json = json.TrimEnd(',') + (is_enum ? "]" : "}");
    
                return json;
    
    
                // ======= local methods ======= 
    
                bool IsEnumerableType(Type type)
                {
                    if (type.IsInterface && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
                        return true;
    
                    foreach (Type intType in type.GetInterfaces())
                    {
                        if (intType.IsGenericType
                            && intType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
                        {
                            return true;
                        }
                    }
                    return false;
                }
            }
        }
    
        /// <summary>
        /// Reads an object instance from an Json file.
        /// <para>Object type must have a parameterless constructor.</para>
        /// </summary>
        /// <typeparam name="T">The type of object to read from the file.</typeparam>
        /// <param name="filePath">The file path to read the object instance from.</param>
        /// <returns>Returns a new instance of the object read from the Json file.</returns>
        public static T ReadFromJsonFile<T>(string filePath) where T : new()
        {
            TextReader reader = null;
            try
            {
                reader = new StreamReader(filePath);
                var fileContents = reader.ReadToEnd();
                return JsonConvert.DeserializeObject<T>(fileContents/*, new JsonInheritenceConverter<object>()*/);
            }
            finally
            {
                if (reader != null)
                    reader.Close();
            }
        }
    
        // tutorial @https://www.codeproject.com/Articles/1201466/Working-with-JSON-in-Csharp-VB#data_structure_types
        // unused
        // TODO: check for actual type in ReadJson
        // TODO: avoid self-referencing-loop-error in WriteJson
        public sealed class JsonInheritenceConverter<T> : JsonConverter
        {
            public override bool CanConvert(Type objectType)
            {
                return typeof(T).IsAssignableFrom(objectType);
            }
    
            public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
            {
                JObject jo = JObject.Load(reader);
                var element = jo.Properties().First();
                return element.Value.ToObject(Type.GetType(element.Name));
            }
    
            public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
            {            
                if (value == null)
                {
                    serializer.Serialize(writer, null);
                    return;
                }
    
                writer.WriteStartObject();
                writer.WritePropertyName(value.GetType().FullName);
                serializer.Serialize(writer, value);
                writer.WriteEndObject();
            }
        }