Как получить значение ключа формата json в массиве? - PullRequest
1 голос
/ 25 октября 2019

Я хочу вернуть определенный тип формата JSON из моего sp. Ниже приведен желаемый формат JSON:

Я использую набор данных для выборки из Query. Я зациклился на строке данных из таблицы. Я использовал тип KeyValuPair для получения данных. Но не в состоянии получить желаемый формат, я получаю только значение ключа формата, но как получить его в метаданных.

Мой желаемый вывод JSON

{
"Metadata": [
{
"Key": "FirstName",
"Value": "ABC"
},
{
"Key": "LastName",
"Value": "XYZ"
}
],
"Length": 25,
"Type": "application/mp3" 
}

C # код для извлечения данных из sp

SqlDataAdapter da = new SqlDataAdapter(cmd);
DataSet ds = new DataSet();
da.Fill(ds);

List<Class> objList = new List<Class>();
List<KeyValuePair<string, string>> keyvalList = new List<KeyValuePair<string, string>>();
foreach (DataRow t in ds.Tables[0].Rows)
{
    Class obj1 = new Class();
    obj1.FirstName = Convert.ToString(t["FirstName "]);
    obj1.LastName= Convert.ToString(t["LastName"]);
    objList.Add(obj1);
    keyvalList.Add(new KeyValuePair<string, string>("FirstName ", Convert.ToString(t["FirstName"])));
    keyvalList.Add(new KeyValuePair<string, string>("LastName", Convert.ToString(t["LastName"]);

}
string JSONresult = JsonConvert.SerializeObject(keyvalList);
return JSONresult;

Моя структура классов

public class Class
{ 
    public string FirstName{ get; set; }              
    public string LastName{ get; set; }   
}

JSON формат, который я получаю

[{\"key":\"FirstName\", \"Value\":\"ABC\"},{\"key":\"LastName\", \"Value\":\"XYZ\"}]

Я получаю ключ-значение JSON, но он не попадает внутрь массива метаданных.

Обновление

var data = new 
            {
                Metadata = dt.AsEnumerable()
        .Select(m => new Header
        {

            key= m.Field<string>("AgentId"),
            Value= m.Field<string>("LastName"),

             FirstName = m["FirstName"].ToString(),
            LastName = m["LastName"].ToString()
        }).ToList(),
                Length = "25",
                Type = "application/mp3"
            };

            string JSONreult = JsonConvert.SerializeObject(data);
            return JSONreult;

Вывод, что я получаю

{
  "Metadata": [
    [
      {
        "Key": "FirstName",
        "Value": "ABC"
      },
      {
        "Key": "LastName",
        "Value": "DEF"
      }
    ],
    [
      {
        "Key": "FirstName",
        "Value": "GEH"
      },
      {
        "Key": "LastName",
        "Value": "IJK"
      }
    ]
  ],
  "Length": 25,
  "Type": "application/json"
}

Вывод Как я хочу

{
    "Metadata": [
        {
            "Key": "FirstName", 
            "Value": "ABC"   
        },   
        {     
            "Key": "LastName",     
            "Value": "XYZ"    
        }
    ], 
    "Length": 25,
    "Type": "audio/mp3", 
}

Разница

Дополнительные [] внутри MetaData, в то время как мне нужен только один массив.

Ответы [ 3 ]

0 голосов
/ 25 октября 2019

Ответ обновляется на основе комментариев

Ваш вопрос состоит из двух частей:

1.Как заполнить DataTable

2.Как сериализовать его в json (в пользовательском виде)

Прежде всего, измените структуру вашего класса, как показано ниже:

public class Metadata
{
    public string FirstName { get; set; }
    public string LasstName { get; set; }
}

public class Data
{
    public IList<Metadata> Metadata { get; set; }
    public int Length { get; set; }
    public string Type { get; set; }
}

Затем вы должны заполнить dt результатами запроса к базе данных, используя Linq:

DataTable dt = new DataTable();
da.Fill(dt);

var listOfData = new Data
{
    Metadata = dt.AsEnumerable()
        .Select(m => new FullName
        {
            Key = m["FirstName"].ToString(),
            Value = m["LastName"].ToString()
        }).ToList(),
    Length = 25,
    Type = "application/mp3"
};

После сериализации listOfData в json с помощью команды var json = JsonConvert.SerializeObject(listOfData);, вывод будет выглядеть следующим образом:

{ 
   "Metadata":[ 
      { 
         "Key":"John",
         "Value":"Smith"
      },
      { 
         "Key":"Adele",
         "Value":"Jones"
      }
   ],
   "Length":25,
   "Type":"application/mp3"
}

Но он отличается от желаемого результата:

{ 
   "Metadata":[ 
      { 
         "Key":"FirstName",
         "Value":"John"
      },
      { 
         "Key":"LastName",
         "Value":"Smith"
      }
   ],
   "Length":25,
   "Type":"application/mp3"
}

Если вы хотите изменить внешний вид вашего json и сериализовать его по-своему, вам нужно реализовать Custon JsonConverter , потому что JsonSerializer не может изменить вашу модель самостоятельно. Для этого вам нужно создать класс и вывести его из JsonConverter и переопределить его методы для формирования ваших узлов так, как вам нравится:

class CustomMetadataConverter<T> : JsonConverter where T : class
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(T);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject obj = new JObject(
        JArray.Load(reader)
              .Children<JObject>()
              .Select(jo => new JProperty((string)jo["Key"], jo["Value"]))
              );
        T result = Activator.CreateInstance<T>();
        serializer.Populate(obj.CreateReader(), result);
        return result;
    }

    public override bool CanRead
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        JArray array = new JArray(
        JObject.FromObject(value)
               .Properties()
               .Select(jp =>
                   new JObject(
                       new JProperty("Key", jp.Name),
                       new JProperty("Value", jp.Value)
                   )
                )
        );

        array.WriteTo(writer);
    }
}

И затем вызывать JsonObject.SerializeObject таким образом, вместо того, чтобы вызывать егокак всегда:

var json = JsonConvert.SerializeObject(listOfData, Formatting.Indented /* set it depend on your need */, new CustomMetadataConverter<Metadata>());

Вы можете десериализовать его таким же образом:

var deserializedObject = JsonConvert.DeserializeObject<JObject>(json, new CustomMetadataConverter<Metadata>());

Вот вывод:

{
  "Metadata": [
    [
      {
        "Key": "FirstName",
        "Value": "John"
      },
      {
        "Key": "LastName",
        "Value": "Smith"
      }
    ],
    [
      {
        "Key": "FirstName",
        "Value": "Adele"
      },
      {
        "Key": "LastName",
        "Value": "Jones"
      }
    ]
  ],
  "Length": 25,
  "Type": "application/json"
}
0 голосов
/ 25 октября 2019

Вам не нужно делать много таких прыжков. Вы могли бы сказать, что используете LinqToSQL или LinqToEF вместе с Json.Net от Newtonsoft от NuGet, и ваш код будет выглядеть так:

var data = new 
{
    MetaData = db.TableName
        .Select(row => new { Key = row.FieldForKey, Value = row.FieldForValue }),
    Length = 25,
    Type = "application/mp3"
};
var json = Newtonsoft.Json.JsonConvert.SerializeObject(data);

Если вы все еще хотите использовать ADO.Net, вы все равно можете сделать это:

var tbl = new DataTable();
new SqlDataAdapter(cmd, "your connection string here").Fill(tbl);

var data = new 
{
    MetaData = tbl.AsEnumerable()
        .Select(t => new { Key = t.Field<string>("KeyColumn"), Value = t.Field<string>("ValueColumn")}),
    Length = 25,
    Type = "application/mp3"
};
var json = Newtonsoft.Json.JsonConvert.SerializeObject(data);

РЕДАКТИРОВАТЬ: Хотя я нахожу это странным, вот полный пример с использованием базы данных образца Northwind:

var tbl = new DataTable();
new SqlDataAdapter(@"Select t.* 
    from Customers c1
    cross apply (select 'FirstName', customerId from customers c2 where c1.CustomerId = c2.CustomerId
               union
               select 'LastName', CompanyName from customers c2 where c1.CustomerId = c2.CustomerId) t([Key], [Value])
               ",@"server=.\SQLExpress2012;Database=Northwind;Trusted_Connection=yes").Fill(tbl);

var data = new 
{
    MetaData = tbl.AsEnumerable()
        .Select(t =>  new { 
            Key = t.Field<string>("Key"), 
            Value = t.Field<string>("Value") } ),
    Length = 25,
    Type = "application/mp3"
};
var json = Newtonsoft.Json.JsonConvert.SerializeObject(data);
0 голосов
/ 25 октября 2019

Вы должны создать класс

public class Data    { 
        public IList<KeyPairValue<string,string>> Metadata{ get; set; }   
     }

, заполнить его своими значениями и затем сериализовать его в Json.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...