content: package com.alibaba.fastjson2.issues;
  
  import com.alibaba.fastjson2.JSON;
  import com.alibaba.fastjson2.JSONWriter;
  import lombok.AllArgsConstructor;
  import lombok.Data;
  import lombok.Getter;
  import lombok.NoArgsConstructor;
  import org.apache.commons.lang3.StringUtils;
  import org.junit.jupiter.api.Test;
  import org.springframework.util.unit.DataSize;
  
  import java.time.Duration;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.Map;
  import java.util.Set;
  
  import static org.junit.jupiter.api.Assertions.assertFalse;
  
  public class Issue764 {
      @Test
      public void test() {
          DockerTest compose = new DockerTest();
          compose.setVersion("3.9");
  
          Service realtimeSvc = new Service();
          realtimeSvc.setImage("real-svc:1.0.21");
          realtimeSvc.putEnv("NETWORK_NAME", "eth0");
          realtimeSvc.putEnv("DEBUG_VERBOSE", "false");
          realtimeSvc.putEnv("SPRING_PROFILES_ACTIVE", "test");
          realtimeSvc.putEnv("SERVER_IP", "172.21.32.180");
          Deploy realtimeSvcDeploy = new Deploy();
          realtimeSvcDeploy.setReplicas(1);
          realtimeSvc.setDeploy(realtimeSvcDeploy);
          compose.addService("realtime-svc", realtimeSvc);
          Service realtimePipe = new Service();
          realtimePipe.setImage("realpipe:1.0.21");
          realtimePipe.putEnv("NETWORK_NAME", "eth0");
          realtimePipe.putEnv("DEBUG_VERBOSE", "false");
          realtimePipe.putEnv("SPRING_PROFILES_ACTIVE", "test");
          realtimePipe.putEnv("SERVER_IP", "172.21.22.180");
          Deploy realtimePipeDeploy = new Deploy();
          realtimePipeDeploy.setReplicas(1);
          realtimePipeDeploy.setResources(new Deploy.Resource().limit(2.5));
          realtimePipe.setDeploy(realtimePipeDeploy);
          compose.addService("realtime-pipe", realtimePipe);
  
          Service platformManagerSvc = new Service();
          platformManagerSvc.setImage("platform:1.0.21");
          platformManagerSvc.putEnv("NETWORK_NAME", "eth0");
          platformManagerSvc.putEnv("DEBUG_VERBOSE", "false");
          platformManagerSvc.putEnv("SPRING_PROFILES_ACTIVE", "test");
          platformManagerSvc.putEnv("SERVER_IP", "172.21.32.180");
          platformManagerSvc.putEnv("HOLLYSYS_LOGIC_IMAGE=nodered:1.3.7_v1.0.21");
          platformManagerSvc.putEnv("HOLLYSYS_UDPIO_ENV[MINIO_FILE_PATH]=/opt/deploy/data/udpio/");
          platformManagerSvc.putEnv("HOLLYSYS_UDPIO_ENV[HOLLYSYS_SERVER_ENABLED]=false");
          platformManagerSvc.putEnv("HOLLYSYS_UDPIO_ENV[HOLLYSYS_PROTOCOL]=udp");
          platformManagerSvc.putEnv("HOLLYSYS_UDPIO_ENV[HOLLYSYS_UDP_PACKAGE_LENGTH]=1000");
          platformManagerSvc.putEnv("hollysys.logic.data=/opt/m7it/logic/");
          Deploy platformManagerSvcDeploy = new Deploy();
          platformManagerSvcDeploy.setReplicas(1);
          platformManagerSvcDeploy.setResources(new Deploy.Resource().limit("4096MB"));
          platformManagerSvc.setDeploy(platformManagerSvcDeploy);
          compose.addService("platform-manager-svc", platformManagerSvc);
  
          JSONWriter.Feature[] FASTJSON_IGNORE_WRITER_FEATURES = {
                  JSONWriter.Feature.BrowserCompatible,
                  JSONWriter.Feature.WriteNullBooleanAsFalse,
                  JSONWriter.Feature.NotWriteDefaultValue,
                  JSONWriter.Feature.IgnoreErrorGetter,
                  JSONWriter.Feature.IgnoreNonFieldGetter
          };
  
          String json = JSON.toJSONString(compose, FASTJSON_IGNORE_WRITER_FEATURES);
          assertFalse("{}".equals(json));
      }
  
      @Data
      public static class DockerTest {
          private String version = "3.8";
          private Map<String, Service> services = new HashMap();
  
          public Map<String, Service> addService(String name, Service service) {
              if (services == null) {
                  services = new HashMap();
              }
              services.put(name, service);
              return services;
          }
      }
  
      @Getter
      public static class Service {
          private String image;
          private Set<String> environment;
          private Deploy deploy;
  
          public Service putEnv(String env) {
              if (environment == null) {
                  environment = new HashSet();
              }
              if (StringUtils.isNotBlank(env) && env.contains("=")) {
                  environment.add(env);
              }
              return this;
          }
  
          public Service putEnv(String key, String value) {
              if (StringUtils.isBlank(key) || StringUtils.isBlank(value)) {
                  return this;
              }
              return putEnv(key + "=" + value);
          }
  
          public final void setImage(String image) {
              this.image = image;
          }
  
          public final void setDeploy(Deploy deploy) {
              this.deploy = deploy;
          }
      }
  
      @Data
      @NoArgsConstructor
      @AllArgsConstructor
      public static class Deploy {
          private String mode = DeployMode.REPLICATED.getValue();
          private Integer replicas = 1;
          private RestartPolicy restartPolicy;
          private Resource resources;
          private Map<String, String> labels;
  
          public Deploy putLabel(String label, String value) {
              if (labels == null) {
                  labels = new HashMap();
              }
              labels.put(label, value);
              return this;
          }
  
          @Getter
          public static enum DeployMode {
              REPLICATED("replicated"),
              GLOBAL("global");
              private String value;
  
              private DeployMode(String value) {
                  this.value = value;
              }
          }
  
          @Data
          @NoArgsConstructor
          @AllArgsConstructor
          public static class RestartPolicy {
              private String condition;
              private Duration delay;
              private Integer maxAttempts;
              private Duration window;
          }
  
          @Data
          @NoArgsConstructor
          @AllArgsConstructor
          public static class Resource {
              private Limit limits;
              private Limit reservations;
  
              public Resource limit(Number cpus, DataSize memory) {
                  limits = new Limit(cpus, memory);
                  return this;
              }
  
              public Resource limit(Number cpus, String memory) {
                  return limit(cpus, StringUtils.isNotBlank(memory) ? DataSize.parse(memory) : null);
              }
  
              public Resource limit(Number cpus) {
                  limits = new Limit(cpus);
                  return this;
              }
  
              public Resource limit(String memory) {
                  if (StringUtils.isNotBlank(memory)) {
                      limits = new Limit(DataSize.parse(memory));
                  }
                  return this;
              }
  
              @Data
              @NoArgsConstructor
              @AllArgsConstructor
              public static class Limit {
                  private Number cpus;
                  private DataSize memory;
  
                  public Limit(Number cpus) {
                      this.cpus = cpus;
                  }
  
                  public Limit(DataSize memory) {
                      this.memory = memory;
                  }
  
                  public final String getMemory() {
                      return memory != null ? memory.toMegabytes() + "M" : null;
                  }
  
                  public final String getCpus() {
                      return cpus != null ? cpus.toString() : null;
                  }
              }
          }
      }
  }
  