3

Can I make these code to one method with generics?

I want return string or string array because my Json file is like below.

Json sample

So I want to do like this.

public static string langFilePath = @"..\..\..\Core\Data\Lang.json";
public static JObject lang = JObject.Parse(File.ReadAllText(langFilePath));

public static string[] GetJsonValue(string key)
{
    string[] values = lang[key].ToObject<string[]>();

    return values;
}

But value of key can not be string array.

It can also be string.

13
  • 2
    Those look like two completely distinct methods, why do you want to use generics here? Also, what is even the point of these methods, you throw away the value of a anyway? Commented Nov 27, 2018 at 19:56
  • sorry, I'm new to C#. Is there a way to do it without using it? Commented Nov 27, 2018 at 19:57
  • 2
    You don't seem to be using the "a" parameter. Commented Nov 27, 2018 at 19:57
  • 2
    Why not just make your function return an array every time? Would make things less complicated. An array with one member isn't the end of the world. Commented Nov 27, 2018 at 20:11
  • 1
    Yes, thank you everyone for your answers. :D Commented Nov 27, 2018 at 20:21

2 Answers 2

2

Rather than returning one of two possible return types, it's probably simpler to just coerce a single string to an array containing that string. Assuming you don't control the Json, you probably want to write a custom JsonConverter. Here's my quick and dirty stab at the problem:

public class LangEntryConverter: JsonConverter<string[]>
{
    // WriteJson implementation only needed if you need to serialize a value back to Json
    public override void WriteJson(JsonWriter writer, string[] value, JsonSerializer serializer)
    {
        if (value.Length == 1)
        {
            writer.WriteValue(value[0]);
        }
        else
        {
            writer.WriteStartArray();
            for (var i = 0; i < value.Length; i++)
            {
                writer.WriteValue(value[i]);
            }
            writer.WriteEndArray();
        }
    }

    public override string[] ReadJson(JsonReader reader, Type objectType, string[] existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var values = new List<string>();
        if (reader.TokenType == JsonToken.StartArray)
        {
            while (reader.Read() && reader.TokenType != JsonToken.EndArray)
            {
                if (reader.TokenType == JsonToken.String)
                {
                    values.Add((string)reader.Value);
                }
                else
                {
                    throw new Exception($"Unexpected token type: {reader.TokenType}");
                }
            }
        }
        else if (reader.TokenType == JsonToken.String)
        {
            values.Add((string)reader.Value);
        }

        return values.ToArray();
    }
}

And then call it like so:

// Note: double-quotations are required for C#'s verbatim string syntax; they are not part of the Json
var json = @"{
  ""foo"": ""one"",
  ""bar"": [""one"", ""two"", ""three""]
}";

var lang = JsonConvert.DeserializeObject<Dictionary<string, string[]>>(json, new LangEntryConverter());
Console.WriteLine(String.Join(", ", lang["foo"]));  // one
Console.WriteLine(String.Join(", ", lang["bar"]));  // one, two, three

Of course, in your particular situation, this may require some tweaking.

Sign up to request clarification or add additional context in comments.

1 Comment

@Stefan Agreed, I started to throw this together (really just to refresh myself because it's been at least a year since I worked with Json.NET in depth) before I had seen all the comments. I decided to leave this here anyway just in case it helps future readers.
0

Use Generic Syntax:

 class Program<T>
{

  public static string langFilePath = @"..\..\..\Core\Data\Lang.json";
 public static JObject lang = JObject.Parse(File.ReadAllText(langFilePath));

    public static T GetJsonValue(string key)
    {
        T values = lang[key].ToObject<T>();

        return values;
    }
}

4 Comments

Hmm, I think the generic parameter is in the wrong place. You have it on Program but it should be on GetJsonValue. Also, it would probably be helpful to show the calling syntax (i.e. how do you call GetJsonValue to get a string vs. a string array).
Use Object: public static object GetJsonValue(string key) { object values = lang[key].ToObject<object>(); return values; }
@MortezaMousavi: Thanks for the follow-up. You can edit your question and put the code in there, that way it's easier for others to catch up ;-)
Ps: I also do think it should be GetJsonValue<T> instead of Program<T>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.