web-dev-qa-db-fra.com

Décompression de GZip Stream à partir de la réponse HTTPClient

J'essaie de me connecter à une API qui renvoie un code JSON codé GZip à partir d'un service WCF (service WCF vers service WCF). J'utilise HTTPClient pour me connecter à l'API et j'ai pu renvoyer l'objet JSON sous forme de chaîne. Cependant, je dois pouvoir stocker les données renvoyées dans une base de données et, en tant que tel, je me suis dit que le meilleur moyen serait de retourner et de stocker l'objet JSON dans un tableau, un octet ou quelque chose du même genre.

Ce qui me pose problème en particulier, c’est la décompression de l’encodage GZip et j’ai essayé de nombreux exemples, mais je ne peux toujours pas l’obtenir.

Le code ci-dessous indique comment établir ma connexion et obtenir une réponse. Il s'agit du code qui renvoie une chaîne à partir de l'API.

public string getData(string foo)
{
    string url = "";
    HttpClient client = new HttpClient();
    HttpResponseMessage response;
    string responseJsonContent;
    try
    {
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        response = client.GetAsync(url + foo).Result;
        responseJsonContent = response.Content.ReadAsStringAsync().Result;
        return responseJsonContent;
    }
    catch (Exception ex)
    {
        System.Windows.Forms.MessageBox.Show(ex.Message);
        return "";
    }
}

J'ai suivi quelques exemples différents comme ceux-ci API StackExchange , MSDN , et quelques-uns sur stackoverflow, mais je ne l'ai pas encore été capable d'obtenir l'un de ceux-ci à travailler pour moi.

Quel est le meilleur moyen d'y parvenir, suis-je même sur la bonne voie?

Merci les gars.

74
Corey

Installez simplement HttpClient comme ceci:

HttpClientHandler handler = new HttpClientHandler()
{
    AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
};

using (var client = new HttpClient(handler))
{
    // your code
}
187
DIG

Ok, j'ai finalement résolu mon problème. S'il y a de meilleurs moyens s'il vous plaît faites le moi savoir :-)

        public DataSet getData(string strFoo)
    {
        string url = "foo";

        HttpClient client = new HttpClient();
        HttpResponseMessage response;   
        DataSet dsTable = new DataSet();
        try
        {
               //Gets the headers that should be sent with each request
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
              //Returned JSON
            response = client.GetAsync(url).Result;
              //converts JSON to string
            string responseJSONContent = response.Content.ReadAsStringAsync().Result;
              //deserializes string to list
            var jsonList = DeSerializeJsonString(responseJSONContent);
              //converts list to dataset. Bad name I know.
            dsTable = Foo_ConnectAPI.ExtentsionHelpers.ToDataSet<RootObject>(jsonList);
              //Returns the dataset                
            return dsTable;
        }
        catch (Exception ex)
        {
            System.Windows.Forms.MessageBox.Show(ex.Message);
            return null;
        }
    }

       //deserializes the string to a list. Utilizes JSON.net. RootObject is a class that contains the get and set for the JSON elements

    public List<RootObject> DeSerializeJsonString(string jsonString)
    {
          //Initialized the List
        List<RootObject> list = new List<RootObject>();
          //json.net deserializes string
        list = (List<RootObject>)JsonConvert.DeserializeObject<List<RootObject>>(jsonString);

        return list;
    }

Le RootObject contient le get set qui va obtenir les valeurs du JSON.

public class RootObject
{  
      //These string will be set to the elements within the JSON. Each one is directly mapped to the JSON elements.
      //This only takes into account a JSON that doesn't contain nested arrays
    public string EntityID { get; set; }

    public string Address1 { get; set; }

    public string Address2 { get; set; }

    public string Address3 { get; set; }

}

Le moyen le plus simple de créer la ou les classes ci-dessus consiste à utiliser json2charp , qui le formatera en conséquence et fournira également les types de données corrects.

Ce qui suit provient d'une autre réponse sur Stackoverflow encore une fois, il ne prend pas en compte le JSON imbriqué.

    internal static class ExtentsionHelpers
{
    public static DataSet ToDataSet<T>(this List<RootObject> list)
    {
        try
        {
            Type elementType = typeof(RootObject);
            DataSet ds = new DataSet();
            DataTable t = new DataTable();
            ds.Tables.Add(t);

            try
            {
                //add a column to table for each public property on T
                foreach (var propInfo in elementType.GetProperties())
                {
                    try
                    {
                        Type ColType = Nullable.GetUnderlyingType(propInfo.PropertyType) ?? propInfo.PropertyType;

                            t.Columns.Add(propInfo.Name, ColType);

                    }
                    catch (Exception ex)
                    {
                        System.Windows.Forms.MessageBox.Show(ex.Message);
                    }

                }
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message);
            }

            try
            {
                //go through each property on T and add each value to the table
                foreach (RootObject item in list)
                {
                    DataRow row = t.NewRow();

                    foreach (var propInfo in elementType.GetProperties())
                    {
                        row[propInfo.Name] = propInfo.GetValue(item, null) ?? DBNull.Value;
                    }

                    t.Rows.Add(row);
                }
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message);
            }

            insert.insertCategories(t);
            return ds.
        }
        catch (Exception ex)
        {
            System.Windows.Forms.MessageBox.Show(ex.Message);

            return null;
        }
    }
};

Enfin, pour insérer le jeu de données ci-dessus dans une table avec des colonnes mappées au JSON, j'ai utilisé la copie en bloc SQL et la classe suivante.

public class insert
{ 
    public static string insertCategories(DataTable table)
    {     
        SqlConnection objConnection = new SqlConnection();
          //As specified in the App.config/web.config file
        objConnection.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["foo"].ToString();

        try
        {                                 
            objConnection.Open();
            var bulkCopy = new SqlBulkCopy(objConnection.ConnectionString);

            bulkCopy.DestinationTableName = "dbo.foo";
            bulkCopy.BulkCopyTimeout = 600;
            bulkCopy.WriteToServer(table);

            return "";
        }
        catch (Exception ex)
        {
            System.Windows.Forms.MessageBox.Show(ex.Message);
            return "";
        }
        finally
        {
            objConnection.Close();
        }         
    }
};

Donc, ce qui précède fonctionne pour insérer du JSON à partir d’une interface WebAPI dans une base de données. Ceci est quelque chose que je dois travailler. Mais je ne m'attends pas à ce que ce soit parfait. Si vous avez des améliorations, veuillez le mettre à jour en conséquence.

0
Corey

J'ai utilisé le code ci-dessous pour décompresser le flux GZip. Ensuite, j'ai utilisé le tableau d'octets décompressé pour obtenir l'objet JSON requis. J'espère que cela pourra aider quelqu'un.

https://www.dotnetperls.com/decompress

var readTask = result.Content.ReadAsByteArrayAsync().Result;
var decompressedData = Decompress(readTask);
string jsonString = System.Text.Encoding.UTF8.GetString(decompressedData, 0, decompressedData.Length);
ResponseObjectClass responseObject = Newtonsoft.Json.JsonConvert.DeserializeObject<ResponseObjectClass>(jsonString);
0
NidhinSPradeep