2
\$\begingroup\$

In my scenario I have list of object in C# code and need to be converted into JavaScript object. But there are certain condition, where the value of the object might be dynamic based on certain key.

I have a following method which will return string as JavaScript Object.

public string ItemToJson()
{
    List < Item > itemObj = GetItemList();
    if (itemObj.Count > 0)
    {
        StringBuilder sbObj = new StringBuilder();
        sbObj.Append("<script> let Items = {");
        var len = itemObj.Count;
        for (int i = 0; i < len; i++)
        {
            sbObj.Append(itemObj[i].Key);
            sbObj.Append(": { placeholder : \" ");
            sbObj.Append(itemObj[i].Placeholder);
            sbObj.Append(" \" , value : \" ");
            if (itemObj[i].Key == "Photo")
            {
                sbObj.Append(GetImage());
            }
            else
            {
                sbObj.Append(itemObj[i].Value);
            }
            sbObj.Append(" \" } ");
            if (i < len - 1)
                sbObj.Append(",");
        }
        sbObj.Append("} </script>");
        return sbObj.ToString();
    }
    else
    {
        return string.Empty;
    }
}

Here is the complete code of working console app.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace String_Builder_Demo
{
    class Program
    {
        public List<Item> GetItemList()
        {
            List<Item> items = new List<Item>
            {
                new Item(){ Key = "FirstName", Placeholder = "##FirstName##", Value="John" },
                new Item(){ Key = "LastName", Placeholder = "##LastName##", Value="Doe"},
                new Item(){ Key = "Email", Placeholder = "##Email##", Value="john.doe@domain.com " },
                new Item(){ Key = "Address", Placeholder = "##Address##", Value="Kathmandu" },
                new Item(){ Key = "Photo", Placeholder = "##Photo##", Value=""}
            };
            return items;
        }

        public string GetImage()
        {
            return "http://via.placeholder.com/350x150";
        }


        static void Main(string[] args)
        {
            Program obj = new Program();
            Console.WriteLine(obj.ItemToJson());
            Console.ReadLine();
        }

        public string ItemToJson()
        {
            List<Item> itemObj = GetItemList();
            if (itemObj.Count > 0)
            {
                StringBuilder sbObj = new StringBuilder();
                sbObj.Append("<script> let Items = {");
                var len = itemObj.Count;
                for (int i = 0; i < len; i++)
                {
                    sbObj.Append(itemObj[i].Key);
                    sbObj.Append(": { placeholder : \" ");
                    sbObj.Append(itemObj[i].Placeholder);
                    sbObj.Append(" \" , value : \" ");
                    if (itemObj[i].Key == "Photo")
                    {
                        sbObj.Append(GetImage());
                    }
                    else
                    {
                        sbObj.Append(itemObj[i].Value);
                    }
                    sbObj.Append(" \" } ");
                    if (i < len - 1)
                        sbObj.Append(",");
                }
                sbObj.Append("} </script>");
                return sbObj.ToString();
            }
            else
            {
                return string.Empty;
            }
        }
    }
    public class Item
    {
        public string Placeholder { get; set; }
        public string Value { get; set; }
        public string Key { get; set; }
    }
}

The above mention code will return following string.

<script>
    let Items = {
        FirstName:
        {
            placeholder: " ##FirstName## ",
            value: " John "
        },
        LastName:
        {
            placeholder: " ##LastName## ",
            value: " Doe "
        },
        Email:
        {
            placeholder: " ##Email## ",
            value: " john.doe@domain.com  "
        },
        Address:
        {
            placeholder: " ##Address## ",
            value: " Kathmandu "
        },
        Photo:
        {
            placeholder: " ##Photo## ",
            value: " http://via.placeholder.com/350x150 "
        }
    }
</script>

How can I optimize the above code and eliminate the if else condition from ItemToJson() method?

\$\endgroup\$
  • \$\begingroup\$ Is there any particular reason you're doing this yourself instead using json.net? \$\endgroup\$ – t3chb0t Jul 17 '18 at 6:21
  • \$\begingroup\$ @t3chb0t all values are in list except ##Photo## so I thing its impossible to use json.net \$\endgroup\$ – Kiran Shahi Jul 17 '18 at 7:04
  • \$\begingroup\$ I'm pretty sure it's possible ;-) you probably just need a custom json-converter for this type. \$\endgroup\$ – t3chb0t Jul 17 '18 at 7:06
  • \$\begingroup\$ @t3chb0t is there any way to remove if else in this case ? \$\endgroup\$ – Kiran Shahi Jul 17 '18 at 7:16
  • \$\begingroup\$ Why do you want to get rid of the if/else statement? What's wrong with it? \$\endgroup\$ – t3chb0t Jul 17 '18 at 7:22
2
\$\begingroup\$

This is a bit off topic... but unless you are pushing a lot of data through this, StringBuilder isn't going to save you much.

Probably worth profiling to see. If you don't need it, then you can make the code pretty simple.

public string ItemToJson()
{
    List<Item> itemObj = GetItemList();
    if ( itemObj.Count <= 0 )
    {
        return string.Empty;
    }

    var parts = itemObj.Select (
        ( item ) =>
        {
            var val = item.Key == "Photo" ? GetImage () : item.Value;
            return $"{item.Key}: {{ placeholder : \" {item.Placeholder} \" , value : \" {val} \" }} ";
        } );

    var json = string.Join ( "," , parts);

    return $"<script> let Items = {{{json}}} </script>";
}
|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ You have very unusual code formatting... spaces everywhere :-o \$\endgroup\$ – t3chb0t Jul 17 '18 at 16:09
  • 1
    \$\begingroup\$ Many years ago, monks found copying books really hard, so they started adding spaces between the words to make it easier to keep track of where you were upto. This caught on as it makes reading the text easlier. One day I hope developers will have the same epiphany. :P \$\endgroup\$ – Nigel Thorne Jul 18 '18 at 5:05
  • \$\begingroup\$ @NigelThorne: hah, I do the same, but not as much as you :P (spaces before ( in method calls, and method definitions) \$\endgroup\$ – apocalypse Jul 18 '18 at 15:54
  • \$\begingroup\$ @apocalypse I was playing with Resharper settings... :) I'm not sure I'll keep all of them going forward but I do think in general developers don't use enough whitespace. \$\endgroup\$ – Nigel Thorne Jul 18 '18 at 23:31
2
\$\begingroup\$

I'd recommend using a library for something like this. Formatting JSON manually difficult and error prone. Json.NET is nice and straight forward in this case.

public string ItemToJson()
{
    var result = new JObject();

    foreach (var property in GetItemList())
    {
        result.Add(property.Key, new JObject
        {
            ["placeholder"] = property.Placeholder,
            ["value"] = property.Key != "Photo"
                ? property.Value
                : "http://via.placeholder.com/350x150"
        });
    }

    return $"<script>let Items = {JsonConvert.SerializeObject(result)};</script>";
}
|improve this answer|||||
\$\endgroup\$
1
\$\begingroup\$

Had to put it here as it was getting too big for comment.

You definitely need to evaluate that condition based on code you have posted. So, the if/else construct is fine. Alternate options will need you to split the list into separate ones which will be more costly operations.

If I really have to nitpick, I would change the key datatype to int or add another property in Item class itself which is a bool. Perhaps something of is this sort:

class Item
{
    private string _key;
    public string Key
    {
        get
        {
            return _key;
        }

        set
        {
            _key = value;
            IsPhoto = (string.Compare(value, "Photo", true) == 0);
        }
    }

    public bool IsPhoto
    {
        get;
        set;
    }
}

This will remove the string comparison in loop and move it to object creation/update action.

|improve this answer|||||
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for?Browse other questions tagged or ask your own question.