You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测Jackson序列化反序列化后及Angular UI端的对象修改?

Great question! When dealing with tracking changes to data objects (including child records) in an Angular 1.6 + Java/Jackson stack, there are several standard, battle-tested approaches you can use instead of building custom logic from scratch. Let’s break them down:

Client-Side (Angular 1.6) Change Tracking

Angular 1.6 has built-in tools and patterns to help you detect modifications, both at the top-level object and child record level:

1. Original State Comparison with angular.copy

This is the most straightforward approach for basic change detection:

  • When your component loads the initial data (e.g., from the server), create a deep copy of the original object using angular.copy() and store it separately:
    $scope.init = function(personData) {
      $scope.person = personData;
      // Store a pristine copy for later comparison
      $scope.pristinePerson = angular.copy(personData);
    };
    
  • When the user clicks save, compare the current object to the pristine copy. For child records, loop through them and use angular.equals() to check for changes, then set the need-to-save flag accordingly:
    $scope.prepareForSave = function() {
      $scope.person.children.forEach((child, index) => {
        if (!angular.equals(child, $scope.pristinePerson.children[index])) {
          child['need-to-save'] = true;
        } else {
          child['need-to-save'] = false;
        }
      });
    };
    
  • After a successful save, update the pristine copy to match the saved state to avoid false positives on subsequent edits.

2. Form-Driven Tracking with $dirty State

If your UI uses Angular's form directives (ng-form or <form>), you can leverage built-in form state properties:

  • Wrap each child record's inputs in a nested ng-form directive. Each form will automatically track whether its fields have been modified via the $dirty property.
  • On save, iterate over the child forms and set need-to-save based on their $dirty status:
    <div ng-repeat="child in person.children" ng-form="childForm">
      <input ng-model="child.name" />
      <!-- Other child fields -->
    </div>
    
    $scope.prepareForSave = function() {
      $scope.person.children.forEach((child, index) => {
        child['need-to-save'] = $scope.childForms[index].$dirty;
      });
    };
    
  • Don’t forget to reset the form’s $dirty state after saving with childForm.$setPristine().

3. Fine-Grained Watchers

For more control over when changes are detected, use Angular’s $watch or $watchCollection:

  • Use a deep watch on the child records array to catch any modifications:
    $scope.$watch('person.children', (newChildren, oldChildren) => {
      if (newChildren && oldChildren) {
        newChildren.forEach((child, index) => {
          if (!angular.equals(child, oldChildren[index])) {
            child['need-to-save'] = true;
          }
        });
      }
    }, true); // The third "true" enables deep object comparison
    
  • Note: Deep watches can impact performance with large datasets, so use this sparingly.
Server-Side (Java/Jackson) Integration

Once the client marks modified child records, ensure your Java backend handles the need-to-save flag correctly with Jackson:

1. Properly Map the need-to-save Field

In your Java entity classes, use Jackson annotations to align with the client-side field name:

public class Child {
    private Long id;
    private String name;

    // Map the snake_case client field to a camelCase Java property
    @JsonProperty("need-to-save")
    private boolean needToSave;

    // Getters and setters
}

public class Person {
    private Long id;
    private String fullName;
    private List<Child> children;

    // Getters and setters
}

2. Optimize Serialization

  • Use @JsonInclude(JsonInclude.Include.NON_DEFAULT) on the Child class to avoid sending the need-to-save field when it’s false (the default value), reducing payload size:
    @JsonInclude(JsonInclude.Include.NON_DEFAULT)
    public class Child {
        // ... existing fields and annotations
    }
    

3. Process the Saved Data

In your controller, check the needToSave flag to decide whether to persist child records:

@PostMapping("/api/persons/save")
public ResponseEntity<Void> savePerson(@RequestBody Person person) {
    // Update or save only modified child records
    person.getChildren().forEach(child -> {
        if (child.isNeedToSave()) {
            childRepository.save(child);
        }
    });
    // Save the parent person
    personRepository.save(person);
    return ResponseEntity.ok().build();
}
Best Practices
  • Hybrid Validation: Always validate changes on the server side too (e.g., compare incoming data to the database state) to prevent client-side tampering of the need-to-save flag.
  • Avoid Overcomplication: For most use cases, the angular.copy + comparison approach is sufficient. Reserve watchers or form tracking for complex UIs.
  • Handle Large Datasets: If you’re dealing with hundreds of child records, consider implementing delta updates (only send modified fields instead of the entire object) to reduce bandwidth usage. Jackson’s ObjectMapper.updateValue() method can merge delta payloads into existing server-side objects.

内容的提问来源于stack exchange,提问作者chrisl08

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:29:08