Ошибка при десериализации json

Здравствуйте.

Имею вот такую JSON строку:

{"id":"3","companies_name":"{EQrn"}
{"id":"6","companies_name":"testName Company"}
{"id":"7","companies_name":"testName Company324324"}
{"id":"8","companies_name":"testName Company"}
{"id":"9","companies_name":"testName Companydfgdfgf"}
{"id":"10","companies_name":"testName Company"}
{"id":"13","companies_name":"testName Company"}

Использую Newtonsoft.Json, вот так:

Companies restoredCompanies = JsonConvert.DeserializeObject<Companies>(result.message);

Если JSON приходит с 1 объектом, все ок, если несколько то возникает ошибка:
«Additional text encountered after finished reading JSON content: {. Path », line 1, position 37.»

Я понимаю причину ошибки, то что я несколько элементов пытаюсь записать в 1 объект, но я пытался сделать и вот так:

List<Companies> restoredCompanies = JsonConvert.DeserializeObject<List<Companies>>(result.message);
// и так:

Companies[] restoredCompanies = JsonConvert.DeserializeObject<Companies[]>(result.message);

А вот класс Companies:

class Companies
    {
        public string id { get; set; }
        public string companies_name { get; set; }
    }

Но что то не получается.

Я понимаю что вопрос мега тупой и очень простой, не судите пожалуйста)

P.S. Спасибо всем огромное!

I need to convert JSON data that I get from a REST API and convert them to CSV for some analytic. The problem is that the JSON data do not necessarily follow the same content, so I can’t define a type for mapping. This has become a challenge that is taking too much of my time. I have already created some code, but of course it is not working as it throws exception on this line

var data = JsonConvert.DeserializeObject<List<object>>(jsonData);

The error is:

Additional information: Cannot deserialize the current JSON object
(e.g. {«name»:»value»}) into type
‘System.Collections.Generic.List`1[System.Object]’ because the type
requires a JSON array (e.g. [1,2,3]) to deserialize correctly.

To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.

Path ‘data’, line 2, position 10.

please let me know what I can do to get this going.

A sample of data would be like this, the fields of data can change very often, for example a new field can be added the next day, so I don’t have the liberty to create a .Net class to map the data.

{
  "data": [
    {
      "ID": "5367ab140026875f70677ab277501bfa",
      "name": "Happiness Initiatives - Flow of Communication/Process & Efficiency",
      "objCode": "PROJ",
      "percentComplete": 100.0,
      "plannedCompletionDate": "2014-08-22T17:00:00:000-0400",
      "plannedStartDate": "2014-05-05T09:00:00:000-0400",
      "priority": 1,
      "projectedCompletionDate": "2014-12-05T08:10:21:555-0500",
      "status": "CPL"
    },
    {
      "ID": "555f452900c8b845238716dd033cf71b",
      "name": "UX Personalization Think Tank and Product Strategy",
      "objCode": "PROJ",
      "percentComplete": 0.0,
      "plannedCompletionDate": "2015-12-01T09:00:00:000-0500",
      "plannedStartDate": "2015-05-22T09:00:00:000-0400",
      "priority": 1,
      "projectedCompletionDate": "2016-01-04T09:00:00:000-0500",
      "status": "APR"
    },
    {
      "ID": "528b92020051ab208aef09a4740b1fe9",
      "name": "SCL Health System - full Sitecore implementation (Task groups with SOW totals in Planned hours - do not bill time here)",
      "objCode": "PROJ",
      "percentComplete": 100.0,
      "plannedCompletionDate": "2016-04-08T17:00:00:000-0400",
      "plannedStartDate": "2013-11-04T09:00:00:000-0500",
      "priority": 1,
      "projectedCompletionDate": "2013-12-12T22:30:00:000-0500",
      "status": "CPL"
    }
 ]
}



namespace BusinessLogic
{
    public class JsonToCsv
    {

       public string ToCsv(string jsonData, string datasetName)
       {
          var data = JsonConvert.DeserializeObject<List<object>>(jsonData);
          DataTable table = ToDataTable(data); 
          StringBuilder result = new StringBuilder();

            for (int i = 0; i < table.Columns.Count; i++)
            {
                result.Append(table.Columns[i].ColumnName);
                result.Append(i == table.Columns.Count - 1 ? "n" : ",");
            }

            foreach (DataRow row in table.Rows)
            {
                for (int i = 0; i < table.Columns.Count; i++)
                {
                    result.Append(row[i].ToString());
                    result.Append(i == table.Columns.Count - 1 ? "n" : ",");
                }
            }

            return result.ToString().TrimEnd(new char[] {'r', 'n'});

        }

        private DataTable ToDataTable<T>( IList<T> data )
            {
            PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
            DataTable table = new DataTable();
            for (int i = 0 ; i < props.Count ; i++)
                {
                PropertyDescriptor prop = props[i];
                table.Columns.Add(prop.Name, prop.PropertyType);
                }

            object[] values = new object[props.Count];
            foreach (T item in data)
                {
                for (int i = 0 ; i < values.Length ; i++)
                    {
                    values[i] = props[i].GetValue(item);
                    }

                table.Rows.Add(values);
                }

            return table;
            }


        }
}

I want to deserialize my json object to my student class

var result = JsonConvert.DeserializeObject<Student>(data);

My json data

{  
"student":{  
  "fname":"997544",
  "lname":"997544",
  "subject":"IT",
  "grade":"F"
}
}

My student class

[Serializable]
public class Student
{
    [JsonProperty("fname")]
    public string FirstName{ get; set; }
    [JsonProperty("lname")]
    public string LastName{ get; set; }
    [JsonProperty("subject")]
    public string Subject { get; set; }
    [JsonProperty("grade")]
    public string Grade { get; set; }
 }

The code does not work, the error says:

Cannot deserialize the current JSON object (e.g. {«name»:»value»}) into type
because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.

asked Aug 22, 2016 at 16:41

Jmocke's user avatar

JmockeJmocke

2691 gold badge9 silver badges20 bronze badges

3

Your JSON string currently represents an object with an inner object property named Student. If you want to deserialize to your Student object your JSON string should look like this:

{  
   "fname":"997544",
   "lname":"997544",
   "subject":"IT",
   "grade":"F"
}

If it’s not easy to change your JSON you could also use JObject to help you like so:

var jobject = JObject.Parse(jsonData);
var student = JsonConvert.DeserializeObject<Student>(jobject["student"].ToString());

Or as others have pointed out you can simply create another class wrapper and deserialize directly to that.

answered Aug 22, 2016 at 16:45

Jesse Carter's user avatar

Jesse CarterJesse Carter

19.8k7 gold badges63 silver badges100 bronze badges

if you have to use your downloaded json then you need to create another model
class for it

[Serializable]
public class Student
{
    [JsonProperty("fname")]
    public string FirstName{ get; set; }
    [JsonProperty("lname")]
    public string LastName{ get; set; }
    [JsonProperty("subject")]
    public string Subject { get; set; }
    [JsonProperty("grade")]
    public string Grade { get; set; }
}

[Serializable]
public class NewModel
{
    public Student Student { get; set; }
}

then deserialize

var result = JsonConvert.DeserializeObject<NewModel>(data);

answered Aug 22, 2016 at 16:43

Mostafiz's user avatar

MostafizMostafiz

7,2153 gold badges27 silver badges42 bronze badges

5

You JSON object is inside a nameless Root / Parent Object.

So Use something like the following.

var result = JsonConvert.DeserializeObject<RootObject>(data);

then your Student instance can be access as result.student

Ex:

string firstName = result.student.FirstName; 

I use Json2CSharp to generate the additional RootObject class.

Here’s all the class definitions

[Serializable]
public class Student
{
    [JsonProperty("fname")]
    public string FirstName{ get; set; }
    [JsonProperty("lname")]
    public string LastName{ get; set; }
    [JsonProperty("subject")]
    public string Subject { get; set; }
    [JsonProperty("grade")]
    public string Grade { get; set; }
 }

[Serializable]
public class RootObject
{
    public Student student { get; set; }
}

answered Aug 22, 2016 at 16:49

Shiva's user avatar

ShivaShiva

20.4k14 gold badges82 silver badges112 bronze badges

Because you’re trying to deal with the object from JSON, it’s easiest to start with

var jStudent = JObject.Parse(jsonData);

You can then go to any sub property of the JObject through key reference and deserialize as you’re expecting.

var student = JsonConvert.DeserializeObject<Student>(jStudent["student"].ToString());

Hope that helps

answered Aug 22, 2016 at 16:55

Matt Bourque's user avatar

Since you cannot change your Json string, you need to modify your class structure to match it. Note that the student object is wrapped in another class. The class structure to use this Json data looks like this:

public class Wrapper
{
    public Student Student { get; set; }
}

public class Student
{
    [JsonProperty("fname")]
    public string FirstName { get; set; }
    [JsonProperty("lname")]
    public string LastName { get; set; }
    [JsonProperty("subject")]
    public string Subject { get; set; }
    [JsonProperty("grade")]
    public string Grade { get; set; }
}

And deserialise like this:

var wrapper = JsonConvert.DeserializeObject<Wrapper>(data);

answered Aug 22, 2016 at 16:47

DavidG's user avatar

DavidGDavidG

113k12 gold badges215 silver badges222 bronze badges

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
[
    {
        "id": 7542826,
        "title": "Адрес 140",
        "address": "Адрес 140",
        "longitude": 05.961548,
        "latitude": 04.742206,
        "kkms": [
            {
                "id": 65231138,
                "orgId": 3122,
                "retailPlaceId": 7128126123,
                "internalName": "000423532061244",
                "model": "ZR2",
                "serialNumber": "0364589429",
                "onlineStatus": 1,
                "status": 4,
                "createdAt": 1580367599792,
                "declineReason": "",
                "fnsKkmId": "15975313354061244",
                "regStatus": "REGISTRATION_SUCCESS",
                "regStatusChangedAt": 165465370307890,
                "fiscalDrive": {
                    "producer": "",
                    "number": "54165453465469161",
                    "activationDate": 1580367540000
                },
                "lastShift": {
                    "kkmId": "5275257275061244",
                    "updateDate": 1752752752396335,
                    "shiftNumber": 187243,
                    "sells": 8895.61,
                    "returns": 0,
                    "lastTransaction": 1597252577410360000,
                    "shiftClosed": false,
                    "fiscalDriveReplaceRequired": false,
                    "fiscalDriveMemoryExceeded": false,
                    "fiscalDriveExhausted": false,
                    "fiscalDocumentsCount": 47,
                    "lastTransactionType": "TICKET"
                }
            },
            {
                "id": 657765130,
                "orgId": 3122,
                "retailPlaceId": 7128126123,
                "internalName": "000433185565000601",
                "model": "ZR2",
                "serialNumber": "08388284512361",
                "onlineStatus": 0,
                "status": 4,
                "createdAt": 1584534534534507,
                "declineReason": "",
                "fnsKkmId": "0004534534534530601",
                "regStatus": "REGISTRATION_SUCCESS",
                "regStatusChangedAt": 15453453453890,
                "fiscalDrive": {
                    "producer": "",
                    "number": "45354345354345566357",
                    "activationDate": 4534534534560000
                },
                "lastShift": {
                    "kkmId": "45354345345300601",
                    "updateDate": 1596094816137,
                    "shiftNumber": 1611,
                    "sells": 0,
                    "returns": 0,
                    "lastTransaction": 1597252577410360000,
                    "shiftClosed": false,
                    "fiscalDriveReplaceRequired": false,
                    "fiscalDriveMemoryExceeded": false,
                    "fiscalDriveExhausted": false,
                    "fiscalDocumentsCount": 0,
                    "lastTransactionType": "OPEN_SHIFT"
                }
            }
        ],
        "kkmsOnlineCount": 2
    }
]

This post explains how to handle errors generated while deserializing the json file.

This can be achieved by implementing an interface “DeserializationProblemHandler” provided by jackson framework as shown below

UnMarshallingErrorHandler


package package1;

import java.io.IOException;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;

public class UnMarshallingErrorHandler extends DeserializationProblemHandler {
    @Override
    public boolean handleUnknownProperty(DeserializationContext ctxt,
            JsonParser jp, JsonDeserializer deserializer,
            Object beanOrClass, String propertyName) throws IOException,
            JsonProcessingException {
        boolean result = false;
        super.handleUnknownProperty(ctxt, jp, deserializer, beanOrClass,
                propertyName);
        System.out.println("Property with name '" + propertyName + "' doesn't exist in Class of type '" + beanOrClass.getClass().getName() + "'");
        return true;
    }
}

In the above code, we are implementing the interface and add our handling logic in “handleUnknownProperty” method. The Jackson framework passes the information to the interface implementers
1) DeserializationContext ctxt
2) JsonParser jp
3) JsonDeserializer deserializer
4) Object beanOrClass
5) String propertyName

Main information needed for us is “beanOrClass” and “propertyName”

beanOrClass –> will have either the bean instance being serialized or Class object that indicates the type of object being created.

propertyName –> the name of the property for which deserializer didn’t find the appropriate setter method to set in the class.

In the above method we are returning true to inform the deserialization process that we have handled the error and it can continue deserializing.

We have to return false, if we want to stop the deserialization immediately. In this case an exception is thrown or content is skipped based on the configuration.

Below is the main code

Main Class


package package1;

import java.io.File;
import java.io.IOException;

import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.DeserializationProblemHandler;

public class UnMarshallingDemo2 {
    public static void main(String[] args) throws JsonMappingException, JsonGenerationException, IOException {
        File file = new File("user1.json");
        
        ObjectMapper objectMapper = new ObjectMapper();
        DeserializationProblemHandler deserializationProblemHandler = new UnMarshallingErrorHandler();
        objectMapper.addHandler(deserializationProblemHandler);
        User user = objectMapper.readValue(file, User.class);
        System.out.println(user);
    }
}

Information about the class to be deserialized

User


package package1;

public class User {
    private Name name;
    private String ssn;
    private String sex;
    private int age;
    private PhoneNumber[] phoneNumbers;
    
    public Name getName() {
        return name;
    }
    public void setName(Name name) {
        this.name = name;
    }
    public String getSsn() {
        return ssn;
    }
    public void setSsn(String ssn) {
        this.ssn = ssn;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public PhoneNumber[] getPhoneNumbers() {
        return phoneNumbers;
    }
    public void setPhoneNumbers(PhoneNumber[] phoneNumbers) {
        this.phoneNumbers = phoneNumbers;
    }
    
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("{");
        sb.append(name).append(",");
        sb.append(ssn).append(",");
        sb.append(sex).append(",");
        sb.append(age).append(",");
        
        for(PhoneNumber phoneNumber : phoneNumbers) {
            sb.append(phoneNumber).append(",");
        }
        sb.append("}");
        return sb.toString();
    }
}

Name


package package1;

public class Name {
    private String firstName;
    private String lastName;
    
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("{");
        sb.append(firstName).append(",");
        sb.append(lastName);
        sb.append("}");
        
        return sb.toString();
    }
}

package package1;

public class PhoneNumber {
    private String areaCode;
    private String part1;
    private String part2;
    
    public String getAreaCode() {
        return areaCode;
    }
    public void setAreaCode(String areaCode) {
        this.areaCode = areaCode;
    }
    public String getPart1() {
        return part1;
    }
    public void setPart1(String part1) {
        this.part1 = part1;
    }
    public String getPart2() {
        return part2;
    }
    public void setPart2(String part2) {
        this.part2 = part2;
    }
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("{");
        sb.append(areaCode).append("-");
        sb.append(part1).append("-");
        sb.append(part2);
        sb.append("}");
        
        return sb.toString();
    }
}

Json data


{
    "name": {
        "firstName":"firstName1",
        "lastName":"lastName1"
        },
    "ssn":"ssn1",
    "sex":"M",
    "age":28,
    "phoneNumbers":[
            {
                "areaCode":"111",
                "part1":"222",
                "part2":"3333"
            },
            {
                "areaCode":"444",
                "part1":"555",
                "part2":"6666"
            }
            ],
    "numbers":[1,2,3,4]
}

In the above json example, “numbers” is a property that doesn’t exist in User class. So when the above code is executed we will get the below error

Output when true is returned

Property with name ‘numbers’ doesn’t exist in Class of type ‘package1.User’
{{firstName1,lastName1},ssn1,M,28,{111-222-3333},{444-555-6666},}

Output when false is returned

Property with name ‘numbers’ doesn’t exist in Class of type ‘package1.User’
Exception in thread “main” com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field “numbers” (class package1.User), not marked as ignorable (5 known properties: “name”, “phoneNumbers”, “ssn”, “age”, “sex”])
at [Source: user1.json; line: 21, column: 13] (through reference chain: package1.User[“numbers”])
at com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException.from(UnrecognizedPropertyException.java:62)
at com.fasterxml.jackson.databind.DeserializationContext.reportUnknownProperty(DeserializationContext.java:851)
at com.fasterxml.jackson.databind.deser.std.StdDeserializer.handleUnknownProperty(StdDeserializer.java:1085)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownProperty(BeanDeserializerBase.java:1389)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.handleUnknownVanilla(BeanDeserializerBase.java:1367)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:266)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:125)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3807)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2691)
at package1.UnMarshallingDemo2.main(UnMarshallingDemo2.java:18)

  • Ошибка при декодировании заполнения oaep windows admin center
  • Ошибка при декодировании заполнения oaep delphi
  • Ошибка при ддос атаке
  • Ошибка при двусторонней печати
  • Ошибка при генерации кода для свойства cursor