Newtonsoft.Json.JsonReaderException: "Additional text encountered after finished reading JSON content
Hello,
I try to get every Object from a big Array provided by an API (steam-API).
I need multiple calls to get all the Objects since they are a "total_count":15228.
This is my method to get the first page, which works perfectly fine:
public static Task LoadAllItemsAsync()
{
int start=0;
string responseData = "";
using (WebClient w = new WebClient())
{
responseData = responseData + w.DownloadString("https://steamcommunity.com/market/search/render/?search_descriptions=0&sort_column=default&sort_dir=desc&appid=730&norender=1&count=100&start=" + start);
Thread.Sleep(3000);
w.Dispose();
}
start = start + 100;
dynamic parsedJson = JsonConvert.DeserializeObject(responseData);
string jsonData = JsonConvert.SerializeObject(parsedJson, Formatting.Indented);
System.IO.File.WriteAllText(System.IO.Path.GetFullPath(@"..\..\SteamData\SteamItems.json"), jsonData);
return Task.CompletedTask;
}
And to get all of the Objects, I try to loop through all pages, by increasing the start value by 100, and here is where I get an exception when I try to deserialize the responsData string. Code:
public static Task LoadAllItemsAsync()
{
int start=0;
string responseData = "";
for(int i = 0; i <= 1; i++)
{
using (WebClient w = new WebClient())
{
responseData = responseData + w.DownloadString("https://steamcommunity.com/market/search/render/?search_descriptions=0&sort_column=default&sort_dir=desc&appid=730&norender=1&count=100&start=" + start);
Thread.Sleep(3000);
w.Dispose();
}
start = start + 100;
}
dynamic parsedJson = JsonConvert.DeserializeObject(responseData); //Newtonsoft.Json.JsonReaderException: "Additional text encountered after finished reading JSON content
string jsonData = JsonConvert.SerializeObject(parsedJson, Formatting.Indented);
System.IO.File.WriteAllText(System.IO.Path.GetFullPath(@"..\..\SteamData\SteamItems.json"), jsonData);
return Task.CompletedTask;
}
I have found something on google, but I don't understand it and I don't know how to apply it on my code. I highly appreciate any answers.
Edit:
What I have tried:
public static Task LoadAllItemsAsync()
{
int start=0;
string responseData = "";
string jsonData = "";
for (int i = 0; i <= 1; i++)
{
using (WebClient w = new WebClient())
{
responseData = responseData + w.DownloadString("https://steamcommunity.com/market/search/render/?search_descriptions=0&sort_column=default&sort_dir=desc&appid=730&norender=1&count=100&start=" + start);
dynamic parsedJson = JsonConvert.DeserializeObject(responseData);
jsonData = jsonData + JsonConvert.SerializeObject(parsedJson, Formatting.Indented);
}
start = start + 100;
}
System.IO.File.WriteAllText(System.IO.Path.GetFullPath(@"..\..\SteamData\SteamItems.json"), jsonData);
return Task.CompletedTask;
}
Please check following code. The first step is to extract c# types from your json - I used https://json2csharp.com/ for that. Then you should iterate through requests and deserialize each into your objects. Collect all the objects you need in a separate list, serialize and write to file.
using Newtonsoft.Json;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Threading;
namespace SteamMarketJson
{
public class Searchdata
{
public string query { get; set; }
public bool search_descriptions { get; set; }
public int total_count { get; set; }
public int pagesize { get; set; }
public string prefix { get; set; }
public string class_prefix { get; set; }
}
public class AssetDescription
{
public int appid { get; set; }
public string classid { get; set; }
public string instanceid { get; set; }
public string background_color { get; set; }
public string icon_url { get; set; }
public int tradable { get; set; }
public string name { get; set; }
public string name_color { get; set; }
public string type { get; set; }
public string market_name { get; set; }
public string market_hash_name { get; set; }
public int commodity { get; set; }
}
public class Result
{
public string name { get; set; }
public string hash_name { get; set; }
public int sell_listings { get; set; }
public int sell_price { get; set; }
public string sell_price_text { get; set; }
public string app_icon { get; set; }
public string app_name { get; set; }
public AssetDescription asset_description { get; set; }
public string sale_price_text { get; set; }
}
public class RootObject
{
public bool success { get; set; }
public int start { get; set; }
public int pagesize { get; set; }
public int total_count { get; set; }
public Searchdata searchdata { get; set; }
public List<Result> results { get; set; }
}
class Program
{
static HttpClient httpClient = new HttpClient();
private const string BASE_URL = "https://steamcommunity.com/market/search/render/?search_descriptions=0&sort_column=default&sort_dir=desc&appid=730&norender=1&count=100&start=";
static void Main(string[] args)
{
int start = 0;
List<Result> results = new List<Result>(); // you probably want to store results only
RootObject rootObject = null;
do
{
var response = httpClient.GetAsync(BASE_URL + start).Result; // use await instead of .Result when used in methods
var body = response.Content.ReadAsStringAsync().Result;
rootObject = JsonConvert.DeserializeObject<RootObject>(body);
if (rootObject.results != null)
{
results.AddRange(rootObject.results);
}
start += 100;
Thread.Sleep(3000);
}
while (start < rootObject.total_count);
// write to file
var jsonResult = JsonConvert.SerializeObject(results);
File.WriteAllText("D:\\file.txt", jsonResult);
// read and deserialize it back
var fileContent = File.ReadAllText("D:\\file.txt");
var items = JsonConvert.DeserializeObject<List<Result>>(fileContent);
}
}
}