Xamarin.Controls – JsonTextView

I had a relatively unique requirement where we needed to list out items in a single list that were originated from Json. That’s obviously pretty straightforward. However, each of these items coming back as Json had DRASTICALLY different properties.

The go-to thought is to use different DataTemplates for each unique type that was coming back. However, there was no consistency on top of around 100 different types we were going to get. This sounds like a design flaw in what is coming down from the server, but we didn’t have control over that.

I put my solution up on GitHub as a reusable control: https://github.com/SuavePirate/JsonTextView

It’s simply a control for Xamarin.Forms that has a bindable property called Json that consumes a Json string. It then takes that Json and puts it into an organized Label using Span classes:

public void SetJson(string json)
{
    try
    {
        var dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(json);
        foreach (var pair in dict)
        {
            var boldSpan = new Span()
            {
                Text = UpperCase ? $"{pair.Key.SplitCamelCase().ToTitleCase()}: " : $"{pair.Key.SplitCamelCase()}: ",
                FontAttributes = FontAttributes.Bold
            };
            var detailSpan = new Span()
            {
                Text = pair.Value.SplitCamelCase().ToTitleCase()
            };
            var lineBreak = new Span()
            {
                Text = "\n"
            };
            FormattedText.Spans.Add(boldSpan);
            FormattedText.Spans.Add(detailSpan);
            FormattedText.Spans.Add(lineBreak);
        }
    }
    catch
    {
        WriteLine("Failed to parse json.");
    }
}

This also uses two extension methodsthat come in handy:

public static string SplitCamelCase(this string str)
{
    return Regex.Replace(
       Regex.Replace(
            str,
            @"(\P{Ll})(\P{Ll}\p{Ll})",
            "$1 $2"
        ),
        @"(\p{Ll})(\P{Ll})",
        "$1 $2"
     );
}

public static string ToTitleCase(this string str)
{
    return string.Join(" ", str.Split(' ').Select(i => $"{i.Substring(0, 1).ToUpper()}{i.Substring(1).ToLower()}").ToArray());
}

The usage is then pretty simple:

XAML


<ContentPage
  ...
  xmlns:sp="clr-namespace:SPControls;assembly=SPControls"
  ...>
    <Grid>
      <sp:JsonTextView Json="{Binding JsonString}" />
    </Grid>
</ContentPage>

Or in C#

...
var jsonTextView = new SPControls.JsonTextView();
jsonTextView.Json = jsonString;
...

Check out the repository for the full code, and help contribute! Fork the repository, add what features you’d like to see, then submit a pull request.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s