Wyciąganie danych z gitlaba

0

Czy ktoś programował wyciąganie danych z Gitlaba. Szukam informacji na temat tego jak zacząć, chciałbym zrobić kilka zestawień informacji z repozytorium Gitalaba do pliku CSV ale nie wiem jak to ugryźć może ktoś może coś podpowiedzieć od czego zacząć. Gdzie znajdę informację jak podpiąć się pod api

2

Proste restowe api. Z czym masz problem?

0

Jeszcze nie problem tylko jeszcze tego nie robiłem i nie wiem jak zacząć. Potrzebuje zrobić np. zestawienie wszystkich tagów z wszystkich projektów jakie mam w Gitlabie. Szukam jakiegoś przykładu na którym mógłbym zacząć a potem za pomocą zapytań kombinować co konkretnie chce osiągnąć

0

Mam dobre wrażenia z taką biblioteką kliencką RestSharp.
Ale jak nic nigdy takiego nie ćwiczyłeś, to jest droga przed tobą

0

Spróbowałem coś zrobić z Microsoft.AspNet.WebApi.Client ale zawiesiłem się na autoryzacji za pomocą tokenu. Jeśli robię to tak jak zamieściłem dostaję response 200. Jeśli jednak próbuję dodać mój token za pomocą client.DefaultRequestHeaders.Add("access-token", accessToken); to otrzymuję zwrotkę 404. Ktoś coś podpowie na szybko?

static async Task RunAsync()
        {
            using (var client = new HttpClient())
            {
                string accessToken = "mój_token";
                client.BaseAddress = new Uri("https://lokalny_gitlab/");
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                //client.DefaultRequestHeaders.Add("access-token", accessToken);

                Console.WriteLine("GET");
                HttpResponseMessage response = await client.GetAsync("/api/v4/projects/515/?private_token=mój_token");
                Console.WriteLine(response);
                Console.ReadLine();
                //if (response.IsSuccessStatusCode)

            }

        }
    }
}
2
aksimoN napisał(a):

Spróbowałem coś zrobić z Microsoft.AspNet.WebApi.Client ale zawiesiłem się na autoryzacji za pomocą tokenu. Jeśli robię to tak jak zamieściłem dostaję response 200. Jeśli jednak próbuję dodać mój token za pomocą client.DefaultRequestHeaders.Add("access-token", accessToken); to otrzymuję zwrotkę 404. Ktoś coś podpowie na szybko?

Ok,

Zerkając pobieżnie po dokumentacji API Gitlaba z tego co widzę, to używają access_token zamiast access-token,

Następnie - dlaczego access_token w headerze jeżeli w przykładach podają go w URL jako

GET https://gitlab.example.com/api/v4/user?access_token=OAUTH-TOKEN

a jeżeli chcesz używać headera to powinieneś użyć przeznaczonego do tego / używanego przez nich headera, czyli jak zgaduje

Key: Authorization
Value: Bearer _token_

curl --header "Authorization: Bearer OAUTH-TOKEN" "https://gitlab.example.com/api/v4/user"

0

Stworzyłem klasę Tag:

public class Tag
    {
        public string id { get; set; }
        public string tag_name { get; set; }
        public string reference { get; set; }
        public string message { get; set; }
        public string release_description { get; set; }
        
    }

I teraz odpytuję GitLaba i chciałbym zdeserializować „content responsa” (jeśli dobrze rozumiem co muszę zrobić) do listy Tagów.
Czyli jeśli otrzymam pozytywną odpowiedź, a dostaję 200 czyli zapytanie działa, chciałbym odpowiedź z API wrzucić do listy

class Program
    {
        static void Main(string[] args)
        {
            RunAsync().Wait();
        }

        static async Task RunAsync()
        {
            using (var client = new HttpClient())
            {
                string apiAccessToken = "?private_token=mój_token";
                string apiString = "/api/v4/";
                string apiReq = "projects/515/repository/tags";
                string apiPath = apiString+apiReq+apiAccessToken;
                client.BaseAddress = new Uri("mojeuri");
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json 
                
               HttpResponseMessage response = await client.GetAsync(apiPath);
                string content = await client.GetStringAsync(apiPath);
                //Console.WriteLine(content);
                List<Tag> tagi = new List<Tag>();

                if (response.IsSuccessStatusCode)
                {
                 tagi  = JsonConvert.DeserializeObject<List<Tag>>(content);
                }
                Console.ReadLine();

            }

        }
    }```

Lista tagi wygląda tak:
![screenshot-20201022145109.png](https://4programmers.net/uploads/attachment/5f/5f91803df29a9.png)
0

@aksimoN:

a co jest w content?

btw: nie wolisz użyć RestSharpa?

0
WeiXiao napisał(a):

@aksimoN:

a co jest w content?

zserializowane dane?

string content = await client.GetStringAsync(apiPath);

screenshot-20201022184550.png

btw: nie wolisz użyć RestSharpa?

Może i bym wolał ale znalazłem jakiś przykład zrobiony w taki sposób i próbuje analogicznie poprzerabiać to do swoich potrzeb ale wychodzi na to że to trochę coś innego.
Na razie działam po omacku

0

@aksimoN:

Z tego co widzę, to masz lekki rozjazd.

Twój Json reprezentuje inne dane niż List<Tag>, już na pierwszy rzut oka widać że nie ma name i obstawiam że coś tutaj powoduje problem (niekoniecznie akurat name).

Weź skopiuj ten JSON i użyj np. w Visual Studio opcji Paste JSON as Classes w jakimś pliku .cs, to ci wygeneruje odpowiednie klasy, a później powinno wystarczyć coś typu DeserializeObject<RootObject>(content), gdzie RootObject jest tą wygenerowaną klasą "najwyższego poziomu".

screenshot-20201022190126.png

0

Twój Json reprezentuje inne dane niż List<Tag>, już na pierwszy rzut oka widać że nie ma name i obstawiam że coś tutaj powoduje problem (niekoniecznie akurat name).

Jest name:
screenshot-20201022193210.png

Ale rzeczywiście coś nie zgrywa z tą klasą.
Skopiowałem zawartość odpowiedzi z RESTer i paste special do nowej klasy Tags:

class Tags
    {

        public class Rootobject
        {
            public Class1[] Property1 { get; set; }
        }

        public class Class1
        {
            public string name { get; set; }
            public string message { get; set; }
            public string target { get; set; }
            public Commit commit { get; set; }
            public Release release { get; set; }
            public bool _protected { get; set; }
        }

        public class Commit
        {
            public string id { get; set; }
            public string short_id { get; set; }
            public DateTime created_at { get; set; }
            public string[] parent_ids { get; set; }
            public string title { get; set; }
            public string message { get; set; }
            public string author_name { get; set; }
            public string author_email { get; set; }
            public DateTime authored_date { get; set; }
            public string committer_name { get; set; }
            public string committer_email { get; set; }
            public DateTime committed_date { get; set; }
            public string web_url { get; set; }
        }

        public class Release
        {
            public string tag_name { get; set; }
            public string description { get; set; }
        }

    }

ale w liscie tagi nadal siedzi to samo, może tu coś robię źle?

tagi = JsonConvert.DeserializeObject<List<Tags>>(content);
0

@aksimoN:

a co ja pisałem wcześniej o root object? :(

0
WeiXiao napisał(a):

@aksimoN:

a co ja pisałem wcześniej o root object? :(

Nie wiem czy nadążam, poprawiłem klasę, zamiast Rootobject mam teraz Tags:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace RestApiToGit
{
           public class Tags
        {
            public Class1[] Property1 { get; set; }
        }

        public class Class1
        {
            public string name { get; set; }
            public string message { get; set; }
            public string target { get; set; }
            public Commit commit { get; set; }
            public Release release { get; set; }
            public bool _protected { get; set; }
        }

        public class Commit
        {
            public string id { get; set; }
            public string short_id { get; set; }
            public DateTime created_at { get; set; }
            public string[] parent_ids { get; set; }
            public string title { get; set; }
            public string message { get; set; }
            public string author_name { get; set; }
            public string author_email { get; set; }
            public DateTime authored_date { get; set; }
            public string committer_name { get; set; }
            public string committer_email { get; set; }
            public DateTime committed_date { get; set; }
            public string web_url { get; set; }
        }

        public class Release
        {
            public string tag_name { get; set; }
            public string description { get; set; }
        }

    }

robię tak:

 HttpResponseMessage response = await client.GetAsync(apiPath);
 var content = await client.GetStringAsync(apiPath);
  List<Tags> tagi = new List<Tags>();
  tagi = JsonConvert.DeserializeObject<List<Tags>>(content);

i niestety mam Property1 null:

screenshot-20201022212217.png

0

@aksimoN

Twój json reprezentuje obiekt który w sobie ma tablicę, a Ty próbujesz zamienić ten obiekt (który ma w sobie tablicę) na listę. poprawione niżej

Zamiast List<Tags> przy Deserialize, to podaj nazwę tej klasy, która ma w sobie te Class1[] Property1, czyli po ostatnich zmianach: Tags

Generalnie tak jak Ci Visual Studio wygenerowało te klasy, to wystarczyło zrobić Deserialize na Rootobject - ten, który miał w sobie tablicę tych twoich pożądanych obiektów.

0
WeiXiao napisał(a):

@aksimoN

Twój json reprezentuje obiekt który w sobie ma tablicę, a Ty próbujesz zamienić ten obiekt (który ma w sobie tablicę) na listę.
Zamiast List<Tags> przy Deserialize, to podaj nazwę tej klasy, która ma w sobie te Class1[] Property1, czyli po ostatnich zmianach: Tags
Generalnie tak jak Ci Visual Studio wygenerowało te klasy, to wystarczyło zrobić Deserialize na Rootobject - ten, który miał w sobie tablicę tych twoich pożądanych obiektów.

No to teraz wywala się na tej lini:

                tagi = JsonConvert.DeserializeObject<Tags>(content);  

I leci do góry do linii:

RunAsync().Wait();

screenshot-20201022215525.png

0

@aksimoN
Podrzuć tu fragment / całego tego jsona

0
WeiXiao napisał(a):

@aksimoN

Podrzuć tu fragment / całego tego jsona

{
    "name": "1.01.004C",
    "message": "",
    "target": "9a8ab4012ad7e1c258e619795c985cbd7ace022f",
    "commit": {
        "id": "9a8ab4012ad7e1c258e619795c985cbd7ace022f",
        "short_id": "9a8ab401",
        "created_at": "2020-10-21T13:52:13.000+02:00",
        "parent_ids": [
            "1f8b35e1cfb78f0d96bbcdc703bb6ff860596adf",
            "4117d1dd6e1f1b8bcbdc1b20caf209b8ca3ff5fa"
        ],
        "title": "AA 1.01.004C",
        "message": "AA 1.01.004C",
        "author_name": "autor.autor",
        "author_email": "[email protected]",
        "authored_date": "2020-10-21T13:52:13.000+02:00",
        "committer_name": "autor.autor",
        "committer_email": "[email protected]",
        "committed_date": "2020-10-21T13:52:13.000+02:00",
        "web_url": "https://lokalny_git/AA/-/commit/9a8ab4012ad7e1c258e619795c985cbd7ace022f"
    },
    "release": {
        "tag_name": "1.01.004C",
        "description": "poprawki\\[nowa wersja]"
    },
    "protected": false
}
1

@aksimoN

Ok, przerobiłem twojego jsona na array tych obiektów i faktycznie mój błąd

screenshot-20201022223746.png

var test = JsonConvert.DeserializeObject<List<Class1>>(json);
public class Class1
{
	public string name { get; set; }
	public string message { get; set; }
	public string target { get; set; }
	public Commit commit { get; set; }
	public Release release { get; set; }
	public bool _protected { get; set; }
}

public class Commit
{
	public string id { get; set; }
	public string short_id { get; set; }
	public DateTime created_at { get; set; }
	public string[] parent_ids { get; set; }
	public string title { get; set; }
	public string message { get; set; }
	public string author_name { get; set; }
	public string author_email { get; set; }
	public DateTime authored_date { get; set; }
	public string committer_name { get; set; }
	public string committer_email { get; set; }
	public DateTime committed_date { get; set; }
	public string web_url { get; set; }
}

public class Release
{
	public string tag_name { get; set; }
	public string description { get; set; }
}

To co pisałem

Twój json reprezentuje obiekt który w sobie ma tablicę, a Ty próbujesz zamienić ten obiekt (który ma w sobie tablicę) na listę.

Miałoby sens gdyby to wyglądało tak

{
	"Dane": 
	[
		{
		},
		{
		}
	]
}

a nie

[{},{}]
0
WeiXiao napisał(a):

U mnie działa

pokaż jak wrzuciłeś tego JSONa do json

0

json: https://pastebin.com/raw/rF6iJxez

var json = File.ReadAllText("test.txt");
0
WeiXiao napisał(a):

json: https://pastebin.com/raw/rF6iJxez

var json = File.ReadAllText("test.txt");

Poszło mi z pliku dla pojedynczego i poszło mi dla całego jsona do listy:

HttpResponseMessage response = await client.GetAsync(apiPath);
                var content = await client.GetStringAsync(apiPath);
                List<Tags> tagi = new List<Tags>();
                tagi = JsonConvert.DeserializeObject<List<Tags>>(content);
                Console.WriteLine(tagi[0].name.ToString());

Wychodzi na to że głównym problemem była źle zbudowana klasa Tags?

0

@aksimoN

Sprawdziłem na twojej poprzedniej implementacji klasy

public string id { get; set; }
public string tag_name { get; set; }
public string reference { get; set; }
public string message { get; set; }
public string release_description { get; set; }

i też mi nie działa, więc najwidoczniej tak.

0

No to ostatnie już pytanko, chcę sobie teraz na tym budować metody które zwracają konkretne obiekty.
Zbudowałem metodę która wypisuje tag_name i description, i to działa:

async void GetProjectTags(string apiReq)
                {
                    string apiPath = apiString + apiReq + apiAccessToken;
                    HttpResponseMessage response = await client.GetAsync(apiPath);
                    var content = await client.GetStringAsync(apiPath);
                    List<Tags> tagi = new List<Tags>();
                    tagi = JsonConvert.DeserializeObject<List<Tags>>(content);
                    foreach (var item in tagi)
                    {
                        Console.WriteLine(item.release.tag_name);
                        Console.WriteLine(item.release.description);
                    } 
                }

Chcę ją przerobić tak żeby zwracała List<Tags>, coś w tym stylu:

async List<Tags> GetProjectTags(string apiReq)
                {
                    string apiPath = apiString + apiReq + apiAccessToken;
                    HttpResponseMessage response = await client.GetAsync(apiPath);
                    var content = await client.GetStringAsync(apiPath);
                    List<Tags> tagi = new List<Tags>();
                    tagi = JsonConvert.DeserializeObject<List<Tags>>(content);
                   return tagi;  
                }

problem w tym że:

The return of async method must be void, Task, Task<T>....
1

List<Tags -> Task<List<Tags>>

Generalnie async void jest czymś, czego się nie zaleca stosować poza pewnym wyjątkiem, a zamiast tego stosować async Task

Async/Await - Best Practices in Asynchronous Programming @ March 2013

1 użytkowników online, w tym zalogowanych: 0, gości: 1