diff --git a/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs b/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs index 6a69c2d9e..9204d5905 100644 --- a/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs +++ b/dotnet/src/dotnetframework/GxClasses/Domain/GxCollections.cs @@ -11,6 +11,7 @@ namespace GeneXus.Utils using System.Linq; using System.Reflection; using System.Runtime.Serialization; + using System.Runtime.Serialization.Json; using System.Text; using System.Xml; using System.Xml.Serialization; @@ -1560,13 +1561,25 @@ public void AddObjectProperty(string name, object prop, bool includeState) public void AddObjectProperty(string name, object prop, bool includeState, bool includeNonInitialized) { IGxJSONAble ijsonProp = prop as IGxJSONAble; + IGxExternalObject extObj = prop as IGxExternalObject; if (ijsonProp != null) { GxSilentTrnSdt silentTrn = prop as GxSilentTrnSdt; if (silentTrn != null) silentTrn.GetJSONObject(includeState, includeNonInitialized); - else + else if (extObj != null) + { + object extInstance = extObj.ExternalInstance; + IGxJSONAble gxJSONAble = extInstance as IGxJSONAble; + if (gxJSONAble != null) + { + JsonObj.Put(name, gxJSONAble.GetJSONObject(includeState)); + } + } + else + { JsonObj.Put(name, ijsonProp.GetJSONObject(includeState)); + } } else { @@ -1699,7 +1712,14 @@ public void FromJSONObject(dynamic obj) IGXBCCollection bcColl; GxSimpleCollection currSimpleColl; IGxJSONAble currJsonProp; + IGxExternalObject currExtProp; CollectionBase currObjColl = currObj as CollectionBase; + + if ((currExtProp = currProp as IGxExternalObject) != null) + { + currProp = currExtProp.ExternalInstance; + } + #if !NETCORE GxObjectCollectionBase currColl; if ((currColl = currProp as GxObjectCollectionBase) != null) @@ -2434,7 +2454,6 @@ public interface IGxCollection : IGxCollection { T GetNumeric(int idx); } - public interface IGxExternalObject { object ExternalInstance { get; set; } @@ -2833,7 +2852,173 @@ public override string ToString() } } + public class GxGenericDictionary : Dictionary, IGxJSONSerializable, IGxJSONAble + { + private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(GxGenericDictionary)); + private readonly DataContractJsonSerializerSettings settings = new DataContractJsonSerializerSettings() { UseSimpleDictionaryFormat = true }; + public void SetDictionary(GxGenericDictionary dictionary) + { + foreach (var entry in dictionary) + { + this[entry.Key] = entry.Value; + } + } + + public bool Get(TKey key, out TValue value) + { + if (TryGetValue(key, out value)) + { + return true; + } + else + { + return false; + } + } + public TValue Get(TKey key) + { + if (TryGetValue(key, out TValue value)) + { + return value; + + } + else + { + return default; + } + } + public List ValueList + { + get{ + return base.Values.ToList(); + } + } + public List KeyList + { + get + { + return base.Keys.ToList(); + } + } + public void Set(TKey key, TValue value) + { + base[key] = value; + } + + public bool RemoveKey(TKey key) + { + return Remove(key); + } + + public void RemoveKeys(List keys) + { + foreach (var key in keys.ToList()) + { + RemoveKey(key); + } + } + public void RemoveAll(GxGenericDictionary dictionary) + { + foreach (var key in dictionary.Keys.ToList()) + { + RemoveKey(key); + } + } + public string ToJson() + { + try + { + return JSONHelper.Serialize(this, settings); + } + catch (Exception e) + { + log.Error("Could not obtain JSON from Dictionary", e); + return ""; + } + } + + public void FromJson(string json) + { + try + { + Clear(); + Dictionary deserializedDictionary = JSONHelper.Deserialize>(json, Encoding.Unicode, null, null, settings); + foreach (var entry in deserializedDictionary) + { + this[entry.Key] = entry.Value; + } + } + catch (Exception e) + { + log.Error("Could not set Dictionary from JSON", e); + } + } + + public string ToJSonString() + { + return ToJson(); + } + + public bool FromJSonString(string s) + { + throw new NotImplementedException(); + } + + public bool FromJSonString(string s, GXBaseCollection Messages) + { + throw new NotImplementedException(); + } + + public bool FromJSonFile(GxFile file) + { + throw new NotImplementedException(); + } + + public bool FromJSonFile(GxFile file, GXBaseCollection Messages) + { + throw new NotImplementedException(); + } + + public void AddObjectProperty(string name, object prop) + { + throw new NotImplementedException(); + } + + public object GetJSONObject() + { + JObject jObj = new JObject(); + foreach (TKey item in Keys) + { + jObj.Accumulate(item.ToString(), this[item]); + } + return jObj; + + } + + public object GetJSONObject(bool includeState) + { + return GetJSONObject(); + } + + public void FromJSONObject(dynamic obj) + { + this.Clear(); + JObject jObj = obj as JObject; + if (jObj != null) + { + foreach (DictionaryEntry item in jObj) + { + base[(TKey)item.Key]= (TValue)item.Value; + } + } + } + + public string ToJavascriptSource() + { + throw new NotImplementedException(); + } + } public class GxDictionary : Dictionary { public bool HasKey(string key) diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/JSONHelper.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/JSONHelper.cs index a857c3f27..6fdc642f4 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/JSONHelper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/JSONHelper.cs @@ -214,7 +214,7 @@ public static string Serialize(T kbObject, Encoding encoding, IEnumerable(T kbObject, Encoding encoding, IEnumerable(T kbObject, DataContractJsonSerializerSettings settings) where T : class + { + try + { + Encoding encoding = Encoding.UTF8; + DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T), settings); + using (MemoryStream stream = new MemoryStream()) + { + serializer.WriteObject(stream, kbObject); + return encoding.GetString(stream.ToArray()); + } + } + catch (Exception ex) + { + GXLogging.Error(log, "Serialize error ", ex); + } + return null; + } internal static string WCFSerialize(T kbObject, Encoding encoding, IEnumerable knownTypes, bool useSimpleDictionaryFormat) where T : class { try @@ -276,12 +294,16 @@ static DataContractJsonSerializerSettings WCFSerializationSettings(IEnumerable(kbObject, encoding, knownTypes, new T()); } public static T Deserialize(string kbObject, Encoding encoding, IEnumerable knownTypes, T defaultValue) where T : class + { + var settings = SerializationSettings(knownTypes); + return Deserialize(kbObject, encoding, knownTypes, defaultValue, settings); + } + internal static T Deserialize(string kbObject, Encoding encoding, IEnumerable knownTypes, T defaultValue, DataContractJsonSerializerSettings settings) where T : class { if (!string.IsNullOrEmpty(kbObject)) { try { - var settings = SerializationSettings(knownTypes); using (MemoryStream stream = new MemoryStream(encoding.GetBytes(kbObject))) { DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T), settings); @@ -299,14 +321,13 @@ public static T Deserialize(string kbObject, Encoding encoding, IEnumerable(string kbObject, Encoding encoding) where T : class, new() { - return Deserialize(kbObject, Encoding.Unicode, null, new T()); + return Deserialize(kbObject, encoding, null, new T()); } public static T Deserialize(string kbObject) where T : class, new() { return Deserialize(kbObject, Encoding.Unicode); } - public static T DeserializeNullDefaultValue(string kbObject) where T : class { return Deserialize(kbObject, Encoding.Unicode, null, null); diff --git a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs index 0e68a2960..75008740a 100644 --- a/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs +++ b/dotnet/src/dotnetframework/GxClasses/Services/GxRestWrapper.cs @@ -804,8 +804,10 @@ protected Task Serialize(object value) #else var responseStream = _httpContext.Response.OutputStream; #endif - var knownTypes = new List(); - knownTypes.Add(value.GetType()); + var knownTypes = new List + { + value.GetType() + }; JSONHelper.WCFSerialize(value, Encoding.UTF8, knownTypes, responseStream); return Task.CompletedTask; diff --git a/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj b/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj index aa96f1c8b..d4f5d804b 100644 --- a/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj +++ b/dotnet/test/DotNetCoreUnitTest/DotNetCoreUnitTest.csproj @@ -15,6 +15,7 @@ + @@ -74,7 +75,7 @@ all - + diff --git a/dotnet/test/DotNetUnitTest/Domain/GxGenericDictionaryTest.cs b/dotnet/test/DotNetUnitTest/Domain/GxGenericDictionaryTest.cs new file mode 100644 index 000000000..b76067c32 --- /dev/null +++ b/dotnet/test/DotNetUnitTest/Domain/GxGenericDictionaryTest.cs @@ -0,0 +1,22 @@ +using GeneXus.Utils; +using Xunit; + +namespace xUnitTesting +{ + public class GxGenericDictionaryTest + { + [Fact] + public void ToJsonTest() + { + GxGenericDictionary dic = new GxGenericDictionary + { + { "key1", 1 }, + { "key2", 2 } + }; + string json = dic.ToJson(); + string expectedJson = "{\"key1\":1,\"key2\":2}"; + Assert.Equal(expectedJson, json); + } + + } +}