ThinkGeo.com    |     Documentation    |     Premium Support

JSON Serializing PointShape

Hello, I've the following code to serialize as JSON a Point I was waiting for some like "X":....,"Y":.....


var Point = new PointShape(X, Y);

DataContractJsonSerializer js = new DataContractJsonSerializer(typeof(PointShape));

MemoryStream ms = new MemoryStream();

js.WriteObject(ms, Point);

context.Response.Write(Encoding.UTF8.GetString(ms.ToArray()));


 


But instead of having X,Y,Z I've got:


 ---------------------------

Message from webpage

---------------------------

{"ABU=":"3fcd4d14-4691-4e40-9dba-ec51cf62d581","wRY=":null,"w04=":0,"wU4=":-8.133108333333336,"wk4=":39.668258333333334}

---------------------------

OK   

---------------------------

 


(I was trying to add an image but was unable, but it's a copy&paste of the alert window with the result.)


Are you using any type of obfuscator or you code like this? What can I do to overcome this?


 



I know the values are: ,"wU4=":-8.133108333333336,"wk4=":39.668258333333334 
 but my problem is that if you are using any king of obfuscate it somehow scrambles this and next update it will not be,"wU4=":-8.133108333333336,"wk4=":39.668258333333334, but something else and my code would become obsolete and erroneous. 


 Rui,



I see the problem. The internal fields are obfuscated so we can’t get the correct name when using DataContractJsonSerializer. Although I don’t think the post-obfuscated name (such as wU4, wk4) will be changed but still that’s not good to use them directly, as you said it will be obsolete and erroneous. So I’m afraid now the best way is to write the JSON serialization code by yourself, here is the sample code to JSON serialize a PointShape, please have a look. Sorry for the inconvenience about it. 




public static class JsonConvertor
        {
            public static string ToJsJson(PointShape point)
            {
                StringBuilder json = new StringBuilder();
                PropertyInfo[] properties = point.GetType().GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                WriteJsonStart(json);
                foreach (PropertyInfo property in properties)
                {
                    object value = property.GetValue(point, null);
                    if (value == null)
                    {
                        value = string.Empty;
                    }
                    if (value.GetType().Equals(typeof(string)))
                    {
                        WriteJsonContent(json, property.Name, value.ToString(), true);
                    }
                    else
                    {
                        WriteJsonContent(json, property.Name, value.ToString(), false);
                    }
                }
                WriteJsonEnd(json);

                return json.ToString();
            }

            private static void WriteJsonStart(StringBuilder json)
            {
                json.Append("{");
            }

            private static void WriteJsonEnd(StringBuilder json)
            {
                json.Append("}");
            }

            private static void WriteJsonContent(StringBuilder json, string key, string value, bool withQuot, params string[] parameters)
            {
                if (parameters.Length != 0)
                {
                    value = String.Format(CultureInfo.InvariantCulture, value, parameters);
                }

                if (withQuot)
                {
                    json.AppendFormat(CultureInfo.InvariantCulture, "\"{0}\":\"{1}\",", key, value);
                }
                else
                {
                    json.AppendFormat(CultureInfo.InvariantCulture, "\"{0}\":{1},", key, value);
                }
            }
        }

By the way, we have fixed the memory issue in this post, just wonder how it works with your app now?


 gis.thinkgeo.com/Support/Dis...fault.aspx


Thanks,


Ben



This is not nice... I'm now getting some problems with this. Until some time ago we could do things like this, but now we are starting to get bugs in ours applications. Are you using the same obfuscator since the 4.5.0 release?


One of our customers complained of some functionality I implemented with this approach. I'm 100% sure it was working in January, but now we have updated ThinkGeo, and that special functionality just turned into a big bug. This is very bad for us. Since we had to undo the update of Thinkgeo, and now have to run intensive testing to our products and finding more and more problems. So, saddly, the memory solution is not yet in production, although it seems a bit better.


I don't understand why is this now. We work with other .NET components, that never give us this kind of problem, for instance Telerik Suite, Aspose, and others. We even have access to the source code of every release, and we do not have to face this kind of difficulties. And although we have access to the source no one in my company uses it, it's not our responsability look into our supplier's code, if we have problems we just comunicate to them and they should fix it. We paid the product so we hope it works always 100%, if not we can't spend internal resources fixing their bugs. But at the end is a warranty that if something goes wrong we the supplier company, for instance Telerik, our products wouldn't be compromise.

In your case we don't have access to the code. Or better yet, we had access to Oracle Provider source code, which you kindlly supllied us. I'm very thankfully for that action. We had some serious performance issue with Oracle provide which I fixed and even give you some directions, so you could also optimize your version.


I understand and even support the decision of obfuscating the code, but maybe you are missing a layer, a non obfuscated layer. This layer's only function would be acting as a proxy between your customers code and your obfuscated logic.


I can't just implement what you suggest, it can even work, but the PointShape was just an example, I use this for a lot of objects. ThinkGeo and non ThinkGeo objects. 

But what can I do, you changed the game's rules in the middle of it, so now I have to adapt my self and my code to your complaince break decisions.


Just take some time thinking in the impact of some decisions you make to you customers code before you do so.

I'm sorry if I seem too... how you say... too upset. But I had some stressful meeting this week related with my intensive internal support to ThinkGeo products, so I hope you understand.


To conclude, thank you Ben for your suggestion. But I've to find another solution.



 Rui,



Sorry for any inconvenience we brought to you.  I understand your feelings and I will try my best to solve your issue. 


We updated the obfuscation strategy from February 15th in Dev Branch. (The related version is 4.5. 107.0). We tested a lot before releasing this daily build package, maybe not as comprehensive as the major public release test, but we confirmed there are no public API changes and we only update the obfuscation for the internal codes, we don’t want to bring any breakings for the users.


For your scenario, one thing I’m not sure is even before the obfuscation updating, the serialized string is not “correct”. For example, use the same code as following:



   static void Main(string[] args)
        {
            PointShape p = new PointShape(90, 80);
            DataContractJsonSerializer serialier = new DataContractJsonSerializer(p.GetType());
            MemoryStream stream = new MemoryStream();
            serialier.WriteObject(stream, p);

            byte[] bytes = stream.ToArray();
            Console.WriteLine(Encoding.UTF8.GetString(bytes, 0, (int)stream.Length));
        }

 With the Assembly 4.5.0.0, we will get the string below:


{"xc6eb2ada450740a4":null,"xd3ffb967b3c25e70":"cbc89317-1564-42bd-bdf1-50a693d02f54","x901da2c3f210765e":0,"x93e3b47115896f10":90,"xa75f91922911cac0":80}


With the Assembly 4.5.119.0, we will get the following string instead. 


{"ABU=":"cf11a8c9-616d-4563-b1cf-315b0898def3","wRY=":null,"xE4=":90,"xU4=":80,"xk4=":0}


We saw the obfuscated name in the serialized string is because the PointShape doesn’t support DataContract Serializing (the class is not marked as [DataContract] and the properties are not marked as [DataMember]). So when we use DataContractJsonSerializer it will return the names of the internal variables which are obfuscated instead of the names for the public properties (Marked as [DataMember]) which are constant.  (We didn’t support DataContract Serializing I remember is because some limitation about polymorphism, we will have another look if that limitation still exists and if we can add it).


If the new obfuscating strategy hurts you, does that mean you were parsing the serialized strings with the old assembly, for example if it’s “x93e3b47115896f10” it means x in your code while if it is “xa75f91922911cac0”, it really means y? So when it now becomes “xE4=” it breaks the codes. 


If that’s your scenario, I’m sorry for the breakings but at the same time, I’m afraid it’s not very good to use the obfuscated names directly. As you said, it would become obsolete and erroneous. A better way is to do the implementation ourselves like the code I provided in the message above. If that’s not your scenario, could you please let me know in detail, like what class/properties do you need for serialization, what’s the code which works before but not working now, etc.? 


Rui, I know you are advanced with Map Suite and we are inspired from many of your thought through the forum, we really appreciate it. I’m really sorry that you are suffering from this update and please let me know what we can do to help you, we will try the best. 



Thanks,


Ben

Hello Ben, you are totally correct. 
 In part the situation was my fault. I should asked you guys to put those attributes in the classes I was using, but I didn’t.  
 Instead I just compared a bunch of versions to see if the names were the same, I was never expecting that you guys changed the obfuscator between minor releases.  
  
 As you can see below from version 4.0 the name was allways the same: 
  
  
  
Product Version: 4.0.58.0
Result JSON: {“xc6eb2ada450740a4”:null,“xd3ffb967b3c25e70”:“31955565-5805-43cf-8196-5a8421151564”,“x901da2c3f210765e”:0,“x93e3b47115896f10”:100001,“xa75f91922911cac0”:25936} 

Product Version: 4.0.118.0
Result JSON: {“xc6eb2ada450740a4”:null,“xd3ffb967b3c25e70”:“c7c3071b-7ce3-4d8c-a996-0aff491dd5be”,“x901da2c3f210765e”:0,“x93e3b47115896f10”:100001,“xa75f91922911cac0”:25936} 

Product Version: 4.0.140.0
Result JSON: {“xc6eb2ada450740a4”:null,“xd3ffb967b3c25e70”:“a604642d-6eec-44f5-b8ed-a96d6acd18ba”,“x901da2c3f210765e”:0,“x93e3b47115896f10”:100001,“xa75f91922911cac0”:25936} 

Product Version: 4.5.0.0
Result JSON: {“xc6eb2ada450740a4”:null,“xd3ffb967b3c25e70”:“786543fd-9425-435c-90e2-1f71a9bb9661”,“x901da2c3f210765e”:0,“x93e3b47115896f10”:100001,“xa75f91922911cac0”:25936} 
 
Product Version: 4.5.0.15
Result JSON: {“xc6eb2ada450740a4”:null,“xd3ffb967b3c25e70”:“9281a33a-b24d-49fa-9e70-02e9ad76b2fc”,“x901da2c3f210765e”:0,“x93e3b47115896f10”:100001,“xa75f91922911cac0”:25936} 
 
Product Version: 4.5.17.0
Result JSON: {“xc6eb2ada450740a4”:null,“xd3ffb967b3c25e70”:“1f67b889-e476-4aeb-828c-ae2fbd6e92c4”,“x901da2c3f210765e”:0,“x93e3b47115896f10”:100001,“xa75f91922911cac0”:25936} 
 
Product Version: 4.5.78.0
Result JSON: {“xc6eb2ada450740a4”:null,“xd3ffb967b3c25e70”:“c0ab5229-48c8-49de-ae90-24aec3848237”,“x901da2c3f210765e”:0,“x93e3b47115896f10”:100001,“xa75f91922911cac0”:25936} 
 
Product Version: 4.5.108.0
Result JSON: {“ABU=”:“fa5d9bfc-d809-4617-b5dc-d3e49e8150de”,“wRY=”:null,“w04=”:0,“wU4=”:100001,“wk4=”:25936} 
 
 
  
 It was by itself a major problem this issue. The real deal is the bunch of issues raised by using thinkgeo, and since I’m allways defende it (because I do beleive this is great piece of work), I’m the one being called when something goes wrong.  
  
 For now, I’ve already fixed the thing. I somehow was expecting for this to happen in a major release so I made my code easy to change. The only problem was really the obfuscator change between minor releases. Internally we have rules that enforce specific tests when a component is updated. But only with major releases. But now, in thinkgeo case, we are also enforcing this tests to be run. 
  
 Since we had until now several situations with ThinkGeo products, there were guys starting to wonder about the product quality, in my opinion, I was able to prove that you are here and are good. The were some issues, is true, but you always shown a great support, so at the end ThinkGeo was great for all the guys again (Until the next booomm :D ).  


By the way, there was a production release this early morning, and until now everything is nice. Seems to be better now the memory and cpu. Now we have to wait to see. By the tests I’ve made in development enviroment there shouldnt be any porblem now. (only the TIFF, we convert them to ECW)

Rui, 
  
 Thanks for your defending and understanding, I’m confident your guys will believe you have had a good choice. We will always be here to help, and hope there is no next boooom:) 
  
 I have a different understanding for the major/minor releases. I think as major release is well tested, it is good to be uses in production, while as we don’t have a thorough test for every minor releases, it might have some issues here and there so it should be well tested by the customer if want to use it in production to take the advantage of the new features or bug fixings. So I agree with you to have more test for the minor releases, for the public release you can even have less test as we must have done a lot. 
  
 Anyway, it’s good you have solved the main issues, just let us know if you need more help and please keep being informative and constructive in the forum, I’m sure people will Learn a lot from your sharing. 
  
 Thanks, 
  
 Ben