phattyD
phattyD

Reputation: 205

C# Object Make the Values of Attributes into json object

I have a C# Object that I need its attribute values into its own json object. I'm struggling with how to do this dynamically. I have attributes in my C# class that have values and I need to make those attribute values the Key/Value pair in the json respectively.

public class TransHelper
{
    public string Key { get; set; }
    public string Translation { get; set; }
}
TransHelper j = new TransHelper { Key = "MyKeyValue", 
                                  Translation = "MyTranslationValue" }; 
// Need to be json like this
// json { MyKeyValue: MyTranslationValue }

How do I make the attribute values get inserted into a new object where j.Key value is the new Key and j.Translation is the new value? I can use newtonsoft or any json libraries out there, I am sure there is something simple I am missing here.

Upvotes: 1

Views: 960

Answers (5)

Nicholas Carey
Nicholas Carey

Reputation: 74277

Here's a custom converter that should do the trick (assuming you're using Newtonsoft Json.Net):

using System;
using Newtonsoft.Json;

namespace ConsoleApp8
{

  public class TransHelper
  {
    public string Key { get; set; }
    public string Translation { get; set; }
  }

  public class MyBlob
  {
    public string Foo { get; set; }
    public TransHelper Bar { get; set; }
  }

  public class TransHelperConverter : JsonConverter<TransHelper>
  {

    public override TransHelper ReadJson( JsonReader reader, Type objectType, TransHelper existingValue, bool hasExistingValue, JsonSerializer serializer )
    {
      string key = null;
      string val = null;
      TransHelper instance = null;

      if ( reader.TokenType != JsonToken.Null )
      {
        if ( reader.TokenType != JsonToken.StartObject )
          throw new JsonReaderException( $"Unexpected Token: ${reader.TokenType}" );

        if ( !reader.Read() )
          throw new JsonReaderException( $"Unexpected EOF in Json" );

        if ( reader.TokenType != JsonToken.EndObject )
        {
          if ( reader.TokenType != JsonToken.PropertyName )
            throw new JsonReaderException( $"Unexpected Token: ${reader.TokenType}" );

          key = (string)reader.Value;
          if ( !reader.Read() )
            throw new JsonReaderException( $"Unexpected EOF in Json" );

          if ( reader.TokenType != JsonToken.String )
            throw new JsonReaderException( $"Unexpected Token: ${reader.TokenType}" );

          val = (string)reader.Value;
          if ( !reader.Read() )
            throw new JsonReaderException( "Unexpected EOF in Json" );

        }

        if ( reader.TokenType != JsonToken.EndObject )
          throw new JsonReaderException( $"Unexpected Token: ${reader.TokenType}" );

        instance = new TransHelper
        {
          Key = key,
          Translation = val,
        };

      }

      return instance;
    }

    public override void WriteJson( JsonWriter writer, TransHelper value, JsonSerializer serializer )
    {

      writer.WriteStartObject();
      writer.WritePropertyName( value.Key );
      writer.WriteValue( value.Translation );
      writer.WriteEndObject();

      return;

    }

  }

  class Program
  {

    static void Main( string[] argv )
    {
      string json = @"
{
  ""Foo"": ""foo-value"",
  ""Bar"": {
    ""source"": ""translated-value""
  },
}".Trim();

      TransHelperConverter converter = new TransHelperConverter();
      MyBlob deserialized = JsonConvert.DeserializeObject<MyBlob>( json, converter );
      string reserialized = JsonConvert.SerializeObject( deserialized, Formatting.Indented, converter );

      return;
    }

  }

}

Upvotes: 1

Gauravsa
Gauravsa

Reputation: 6524

Its better to use containers like Dictionary with <Key, Value>, then you can use Newtonsoft.Json (better than JavaScriptSerializer), the code will look like this:

JsonConvert.SerializeObject(dict);

example:

var foo = new Dictionary<string, string>();

foo.Add("key1", "value1");
foo.Add("key2", "value2");
foo.Add("key3", "value3");
foo.Add("key4", "value4");

Console.WriteLine(JsonConvert.SerializeObject(foo));
// outputs { "key1":"value1","key2":"value2","key3":"value3","key4":"value4"}

Upvotes: 1

Joe Phillips
Joe Phillips

Reputation: 51130

public class TransHelper
{
    public string Key { get; set; }
    public string Translation { get; set; }
}

public static void Main()
{
    var myList = new List<TransHelper> {
        new TransHelper { Key = "K1", Translation = "T1" },
        new TransHelper { Key = "K2", Translation = "T2" },
        new TransHelper { Key = "K3", Translation = "T3" }
    };

    var dict = myList.ToDictionary(t => t.Key, t => t.Translation);
    //Serialize dict to Json using Newtonsoft.Json (JSON.Net) or Utf8Json libraries
}

Upvotes: 2

Kzryzstof
Kzryzstof

Reputation: 8382

The way I would do such thing is by implementing a custom JsonConverter (doc).

There is this question on SO that can give more details on how to do it.

Here is one way to do this:

public class TransHelperConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        var transHelperInst = value as TransHelper;

        if(transHelperInst is null)
             throw new ArgumentException();

        //  Creates the Json property. 
            var property = new JProperty(transHelperInst.Key, transHelperInst.Translation);

        //  Adds it the Json object.
        var transHelperObject = new JObject();
        transHelperObject.AddFirst(property);

        //  Writes the object.
        transHelperObject.WriteTo(writer);
   }

   public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
   {
       throw new NotImplementedException("Unnecessary because CanRead is false. The type will skip the converter.");
   }

  public override bool CanRead => false;

  public override bool CanConvert(Type objectType)
  {
      return objectType == typeof(TransHelper);
  }
}

Now, you can use this converter like this:

var serializedValue = JsonConvert.SerializeObject(new TransHelper {Key = "MyKeyValue", Translation = "MyTranslationValue"}, Formatting.Indented, new TransHelperConverter());

This will give you the following result:

{
  "MyKeyValue": "MyTranslationValue"
}

Upvotes: 1

Yatin
Yatin

Reputation: 1198

I think you can implement the generic abstract JsonConverter from Json.NET class to achieve this.

Here's the converter implementation:

public class MySerializer : JsonConverter<TransHelper>
{
    public override TransHelper ReadJson(JsonReader reader, Type objectType, TransHelper existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override void WriteJson(JsonWriter writer, TransHelper value, JsonSerializer serializer)
    {
        if(value == null) return;
        writer.WritePropertyName(value.Key);
        writer.WriteValue(value.Translation);
    }
}

Here's how you call it:

var j = new TransHelper
{
    Key = "MyKeyValue",
    Translation = "MyTranslationValue"
};

var jsonString = JsonConvert.SerializeObject(j, Newtonsoft.Json.Formatting.Indented, new MySerializer());

Upvotes: 1

Related Questions