。゚(*´□`)゚。

코딩의 즐거움과 도전, 그리고 일상의 소소한 순간들이 어우러진 블로그

[네이버클라우드] 클라우드 기반의 개발자 과정 7기/웹프로그래밍

[NC7기-48일차(7월3일)] - 웹프로그래밍 29일차

quarrrter 2023. 7. 3. 20:32

*Json 형식으로 입출력하기

JavaScript Object Notation : 자바스크립트 객체 리터럴 문법을 모방하여 만든 텍스트 파일 포맷 

 

JSON (JavaScript Object Notation)은 데이터를 표현하기 위한 경량의 데이터 교환 형식으로, 텍스트로 구성되며, 일반적으로 데이터를 전송하거나 저장하기 위해 사용됩니다

 

1. 자바스크리비트 객체 리터럴

문자열 - "문자열" , '문자열'

숫자 - 314 3.14 (넘버타입 동일. 부동소수점 어쩌고 없음)

논리 - true/false

객체 - { name : "홍길동", age: 20, working: true }

name : property name - 그냥 적어도 되고, "name ", 'name ' 더블,싱글로 적어도 상관없다. 

"홍길동": property value 

 

자바스크립트와 비슷하지만 약간 다른 

Json 포맷

{ "name" : "홍길동", "age" : 20, "working": true}

property name: 반드시 큰따옴표를 사용해서 적어야한다. 

property valu: 문자열은 반드시 큰따옴표 사용 

         

 

Json 인코딩 / 디코딩

JSON  --decoding(deserialize)-->  자바스크립트 객체
또는 XML
(JSON이 XML보다 간결해서 더 많이 쓰는 추세임)
<---encoding(serialize)---  
JSON 형식의 문자열  JSON 라이브러리를 통해
---------------------------------------->
<-------------------------------------
객체 
-자바스크립트
자바객체
C 구조체
C++ 객체 ...
  Java -> Gson (구글에서 만듬)
         ->Jackson
 

 

 

Gson 다운 받기

https://central.sonatype.com/?smo=true 

gson 최신 라이브러리 선택 후 `build.gradle` 빌드 스크립트 파일 변경
클린, 재실행
라이브러리에서 확인 !

 

"nm" : "홍길동"  필드명으로 프러퍼티 네임을 설정함 ,,,,

필드명으로 프러퍼티 네임을 설정함 ,,,,

필드명과 프러퍼티 명이 다를경우 필드명을 우선함. 

 

 

 

 

 

jackson

GSON과 동일한 방법으루 ~
"name" : " 홍길동"   네임이 프러퍼티 네임으로 되어있음

필드명과 프러퍼티 명이 다를경우 프러퍼티를 우선함 

 

JSON 출력 시 필드 명과 프로퍼티 명 

=> 필드 명과 프로퍼티 명을 다르게 쓰지 말자 ~ (+개발의 일관성을 위해서라두,,)

class Member {

	String nm;   // <-- field : 필드명 nm
    
    void setName(...){...}
    String getName(){...}    // property= setter, getter : 
    
    						//프로퍼티명 name 
                            -> set/get 제거
                            -> 나머지 메서드명에서 첫번째 알파벳을 소문자로 한 이름 
                            
                            프로퍼티 명과 필드 명이 다를 경우 
                            GSON : 필드 명 사용 
                            JACKSON : 프로퍼티 명 사용

JSON 문자열을 해석하여 객체를 생성하기

    // 1) JSON 문자열 준비
    String jsonStr = "{\"no\":100,\"name\":\"홍길동\",\"email\":\"hong@test.com\",\"password\":\"1111\",
    \"photo\":\"hong.gif\",\"tel\":\"010-2222-1111\",\"registeredDate\":\"1월 24, 2022\"}";

    // 2) JSON 처리 객체 준비
    Gson gson = new Gson();

    // 3) JSON 문자열을 가지고 객체 만들기
    Member m = gson.fromJson(jsonStr, Member.class);

 Member.class : 파일 확장자 아니고 ,,1!!! member class의 스태틱 변수임 !!!!!!!!! 여기 안에 클래스 정보(=멤버타입)를 담고 있는 객체 정보가 들어있음. 

 gson 기본 날짜 형식 : 7월 3, 2023

▷ 일치하는 프러퍼티가 없으면 name=null

 


Gson에서 날짜 다루기 new GsonBuilder()  + 설정(setDateFormat("yyyy-MM-dd") 를 통해 create() 객체 :GSON (GSON의 인스턴스)생성. :GSON  은 설정된 규칙에 따라서 

Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create();

Date - > "yyyy-MM-dd:

 

yyyy  / MM  / dd / HH / mm / ss

 

GoF의 Builder 패턴1. new 명령으로 직접 인스턴스 생성 // new Gson() => :Gson

(인스턴스 생성과정이 복잡할 경우, 번거로울 경우)

2. 도우미 객체를 통해 인스턴스를 생성  // ? => :Gson

도우미 객체: GsonBuilder 

   <new로 생성>
   GsonBuilder builder = new GsonBuilder();
    builder.setDateFormat("yyyy-MM-dd");
    Gson gson = builder.create();
    
    <builder 생성>
    Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create();

 

 

 

    // 2) JSON 처리 객체 준비
    // Date 타입의 값을 내보내고 가져올 때 사용할 변환 도구를 준비
    // 그 중 Date 타입의 프로퍼티 값을 JSON 문자열로 바꿀 때 호출된다.
    class GsonDateFormatAdapter implements JsonSerializer<Date> {
    	
    	private DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
		@Override
		public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) {
			// 객체를 Json 문자열로 변환할 때 호출된다. 
			String str = dateFormat.format(src);
			return new JsonPrimitive(str);
		}
    }
    
  //Gson 객체를 만들어 줄 도우미 객체 
    GsonBuilder builder = new GsonBuilder();
    
    //Date 타입의 프로퍼티 값을 JSON 형식의 문자열로 바꿔줄 변환기를 등록한다. 
    builder.registerTypeAdapter(
    		Date.class, //원래 데이터의 타입 
    		new GsonDateFormatAdapter()//Date 형식의 데이터를 JSON문자열로 바꿔줄 변환기
    		);
    
    Gson gson = builder.create();

    // 3) 객체의 값을 JSON 문자열로 얻기
    String jsonStr = gson.toJson(m);

    System.out.println(jsonStr);
  }
}

** 잘모르겠음 공부하기 , , ; ; ; 

시리얼라이즈 호출 될 때마다 ,,,  시간 정보를 담고 있는 date객체를 받아서 받고 받고 받아서 JsonPrimitive 에 담아서 리턴 

 // 2) JSON 처리 객체 준비
    class GsonDateFormat implements JsonDeserializer<Date> {
    								//오리지널을 특정으로 바꾸는건: encoding
                         
                         
   ++아답터 등록,,
   GsonBuilder builder = new GsonBuilder();
    builder.registerTypeAdapter(Date.class. new GsonDateFormat());
    Gson gsonn = builder .create();

 

JSON 문자열 : 배열 다루기

JSON 배열 형식 - [{ 객체 정보 },{ 객체 정보}, ...]

=> [

{"프로퍼티명":값,"프로퍼티명":값, ...},

{"프로퍼티명":값,"프로퍼티명":값, ...},

{"프로퍼티명":값,"프로퍼티명":값, ...},

...

]

public class Exam0210 {
  public static void main(String[] args) {

    // 1) 배열 준비
    Member m1 = new Member();
    m1.setNo(101);
    m1.setName("홍길동");
    m1.setEmail("hong@test.com");
    m1.setRegisteredDate(new Date(System.currentTimeMillis()));

    Member m2 = new Member();
    m2.setNo(102);
    m2.setName("임꺽정");
    m2.setEmail("leem@test.com");
    m2.setRegisteredDate(new Date(System.currentTimeMillis()));

    Member m3 = new Member();
    m3.setNo(103);
    m3.setName("안창호");
    m3.setEmail("ahn@test.com");
    m3.setRegisteredDate(new Date(System.currentTimeMillis()));

    Member[] members = {m1, m2, m3};  // new Member {m1, m2, m3} 에서   new Member 생략가능 

    String jsonStr = new Gson().toJson(members);

    System.out.println(jsonStr);
  }
}

 

JSON 문자열 --> 객체 : 배열 다루기
public class Exam0220 {
  public static void main(String[] args) {

    String jsonStr = "[{\"no\":101,\"name\":\"홍길동\"},{\"no\":102,\"name\":\"임꺽정\"},{\"no\":103,\"name\":\"안창호\"}]";

    Member[] members = new Gson().fromJson(jsonStr, Member[].class);

    for (Member m : members) {
      System.out.println(m);
    }
  }
}

 

객체 --> JSON 문자열 : 컬렉션 다루기

    // 1) ArrayList 준비
    Member m1 = new Member();
    m1.setNo(101);
    m1.setName("홍길동");
    m1.setEmail("hong@test.com");
    m1.setRegisteredDate(new Date(System.currentTimeMillis()));
    
    m2 ..
    m3 ..
    
     String jsonStr = new Gson().toJson(list);
    System.out.println(jsonStr);
  }
  
JSON 컬렉션 형식 - [{ 객체 정보 },{ 객체 정보 }, ...]
 => 배열을 출력한 것과 같다.
   JSON은 배열과 컬렉션을 구분하지 않는다.


 

 

 

객체 --> JSON 문자열

public class Exam0320 {
  public static void main(String[] args) {

    String jsonStr = "[{\"no\":101,\"name\":\"홍길동\"},{\"no\":102,\"name\":\"임꺽정\"},{\"no\":103,\"name\":\"안창호\"}]";

    // 1) TypeToken 클래스의 서브 클래스를 만든다.
    class MyTypeToken extends TypeToken<Collection<Member>> {
    }

    // 2) TypeToken 객체 준비
    MyTypeToken typeToken = new MyTypeToken();

    // 3) TypeToken 객체를 통해 Type 구현체를 얻는다.
    Type collectionType = typeToken.getType();


    // 4) Type 객체에 저장된 정보를 바탕으로 JSON 문자열로부터 컬렉션 객체를 만든다.
    Collection<Member> list = new Gson().fromJson(jsonStr, collectionType);

    for (Member m : list) {
      System.out.println(m);
    }
  }
}

익명클래스로 간결하게 나타낼 수 있음 

    Type collectionType = new TypeToken<Collection<Member>>(){}.getType();

    Collection<Member> list = new Gson().fromJson(jsonStr, collectionType);

1) TypeToken 클래스의 서브 클래스를 만든다.

//TypeToken 클래스는 제네릭 타입을 표현하는 데 사용됩니다. 
//제네릭 타입은 컴파일 타임에 타입 안정성을 제공하기 위해 도입된 자바의 기능입니다. TypeToken 클래스를 사용하면 제네릭 타입을 동적으로 나타낼 수 있으며, 
//타입의 정보를 런타임에 쿼리하고 조작할 수 있습니다.

  3) TypeToken 객체를 통해 Type 구현체를 얻는다.

    Type collectionType = typeToken.getType();
    getType() 메서드를 호출하면 TypeToken 객체가 나타내는 제네릭 타입의 정보를 가져올 수 있습니다. 
    이는 런타임에 제네릭 타입에 대한 정보를 쿼리하고 조작하는 데 사용될 수 있습니다.
   4) Type 객체에 저장된 정보를 바탕으로 JSON 문자열로부터 컬렉션 객체를 만든다.

    Collection<Member> list = new Gson().fromJson(jsonStr, collectionType);

    fromJson 메서드는 JSON 라이브러리에서 제공하는 기능 중 하나로, 
   주로 JSON 데이터를 자바 객체로 변환하는 데 사용됩니다.

파라미터 
1. JSON 문자열 (String): 변환할 대상이 되는 JSON 형식의 문자열로 JSON 데이터를 포함하고 있어야 합니다.

2. 변환할 타입 (Type): JSON 문자열을 어떤 타입으로 변환할지를 나타내는 Type 객체로 주로 클래스나 제네릭 타입을 나타내는데 사용됩니다. 

JSON 문자열 --> 객체

**JSON 배열 -> Collection 객체 

 

 

Collection<Member> list = gson.fromJson(Json배열, type)

type : Collection<Member>가 들어있는,,,

 

그냥 Type을 넣으면 안 됨 ,, !
맞는거

 


 

 

default 메서드 목적 

interface에 새 규칙이 추가되면, 기존 interface를 implements한 클래스들이 오류가 뜸. 

기존 구현체들을 헤치지 않으면서, 새 규칙을 추가할 방법이 없을까,,!? 

 

default 메서드 등장 ! 

default autoshutdown() {대충구현}  -> 추상메서드가 아니라 구현된 메서드이기때문에 기존 구현체에 영향을 주지 않는다. (이미 구현된건 implements한 클래스들이 다시 구현안해도됨 ,, ! )

단점: 추상메세드가 아니기 때문에 구현을 강제할 수 없다. => 인터페이스 존재이유가 사라진다. 


객체 --> JSON 문자열 : 다른 객체를 포함하는 경우

다른 객체를 품고 있는 경우

JSON 문자열 --> 객체 : 다른 객체를 포함하는 경우

6 최종으로 Board 객체 리턴


JSON 데이터를 가지고 객체를 생성할 때 특정 타입의 객체로 만들어주는 어댑터
 => 프로퍼티의 존재 유무에 따라 Manager를 생성하든가 Teacher를 생성하는 일을 한다.

 

// JSON 문자열 --> 객체 : 다른 객체를 여러 개 포함하는 경우

public class Exam0621 {
  public static void main(String[] args) {

    String jsonStr = "[{\"position\":\"대리\",\"fax\":\"02-1111-2222\",\"no\":101,\"name\":\"홍길동\",\"email\":\"hong@test.com\",\"registeredDate\":\"9월 16, 2021\"},{\"major\":\"컴퓨터공학\",\"hourPay\":10000,\"no\":103,\"name\":\"안창호\",\"email\":\"ahn@test.com\",\"registeredDate\":\"9월 16, 2021\"}]";

  // JSON 데이터를 가지고 객체를 생성할 때 특정 타입의 객체로 만들어주는 어댑터
    class MyJsonDeserializer implements JsonDeserializer<Member> {
      @Override
      public Member deserialize(JsonElement json, Type typeOfT,
          JsonDeserializationContext context) throws JsonParseException {

        JsonObject jsonObject = json.getAsJsonObject(); // 문자를 jsonObject로 만들기 

        if (jsonObject.get("position") != null) {
          return context.deserialize(jsonObject, Manager.class);// jsonobject에 들어있는걸 manager에 담아서 내줘 ,,! 
        } else {
          return context.deserialize(jsonObject, Teacher.class);
        }
      }
    }

    // Gson 객체를 만들어주는 공장
    GsonBuilder gsonBuilder = new GsonBuilder();

    // 공장에 객체 생성기(JsonDeserializer)를 꼽는다.
    gsonBuilder.registerTypeAdapter(Member.class, new MyJsonDeserializer());

    // 공장을 통해 Gson 객체를 준비한다.
    Gson gson = gsonBuilder.create();

    // Gson 객체가 JSON 데이터를 가지고 객체를 생성할 때 알아야 하는 객체 타입 정보 준비
    Type collectionType = TypeToken.getParameterized(Collection.class, Member.class).getType();

    // JSON 데이터를 읽어서 주어진 타입의 객체를 생성한다.
    // => 단 내부에 설정된 객체 어댑터(JsonDeserializer)를 이용하여 객체를 생성한다.
    Collection<Member> list = gson.fromJson(jsonStr, collectionType);

    for (Member m : list) {
      System.out.println(m);
    }
  }
}

 

710

맵객체 --> JSON 문자열

해쉬맵도 자바 일반 객체처럼 프러퍼티:값  이렇게 출력됨 

// 자바 기본 타입과 객체를 묶어서 JSON으로 내보내기
Manager mgr = new Manager();
mgr.setNo(101);
mgr.setName("홍길동");
mgr.setEmail("hong@test.com");
mgr.setRegisteredDate(new Date(System.currentTimeMillis()));
mgr.setPosition("대리");
mgr.setFax("02-1111-2222");


HashMap<String,Object> params = new HashMap<>();
params.put("no", String.valueOf(100));
params.put("title", "Hello");
params.put("manager", mgr);


String jsonStr = new Gson().toJson(params);


System.out.println(jsonStr);
// 자바 기본 타입과 객체를 묶어서 JSON으로 내보내기
Manager mgr = new Manager();
mgr.setNo(101);
mgr.setName("홍길동");
mgr.setEmail("hong@test.com");
mgr.setRegisteredDate(new Date(System.currentTimeMillis()));
mgr.setPosition("대리");
mgr.setFax("02-1111-2222");


HashMap<String,String> params = new HashMap<>();
params.put("no", String.valueOf(100));
params.put("title", "Hello");
params.put("manager", new Gson().toJson(mgr));


String jsonStr = new Gson().toJson(params);


System.out.println(jsonStr);
// 자바 기본 타입과 객체를 묶어서 JSON으로 내보내기
Manager mgr = new Manager();
mgr.setNo(101);
mgr.setName("홍길동");
mgr.setEmail("hong@test.com");
mgr.setRegisteredDate(new Date(System.currentTimeMillis()));
mgr.setPosition("대리");
mgr.setFax("02-1111-2222");


ManagerParam param = new ManagerParam();
param.no = 100;
param.title = "Hello";
param.manager = mgr;


String jsonStr = new Gson().toJson(param);


System.out.println(jsonStr);

1

JSON 문자열 --> 객체 : 다른 객체를 여러 개 포함하는 경우

String jsonStr = "{\"no\":100,\"manager\":{\"position\":\"대리\",\"fax\":\"02-1111-2222\",\"no\":101,\"name\":\"홍길동\",\"email\":\"hong@test.com\",\"registeredDate\":\"10월 5, 2021\"},\"title\":\"Hello\"}";

Map<String,Object> map = new Gson().fromJson(jsonStr, Map.class);

Object v1 = map.get("no");
Object v2 = map.get("title");
Object v3 = map.get("manager");

System.out.println(v1.getClass().getName());
System.out.println(v2.getClass().getName());
System.out.println(v3.getClass().getName());

System.out.println(map.get("no"));
System.out.println(map.get("title"));
System.out.println(map.get("manager"));
String jsonStr = "{\"no\":\"100\",\"manager\":\"{\\\"position\\\":\\\"대리\\\",\\\"fax\\\":\\\"02-1111-2222\\\",\\\"no\\\":101,\\\"name\\\":\\\"홍길동\\\",\\\"email\\\":\\\"hong@test.com\\\",\\\"registeredDate\\\":\\\"10월 5, 2021\\\"}\",\"title\":\"Hello\"}";

Map<String,String> map = new Gson().fromJson(jsonStr, Map.class);

String v1 = map.get("no");
String v2 = map.get("title");
String v3 = map.get("manager");

System.out.println(v1);
System.out.println(v2);
System.out.println(v3);

Manager mgr = new Gson().fromJson(v3, Manager.class);
System.out.println(mgr);
String jsonStr = "{\"no\":100,\"title\":\"Hello\",\"manager\":{\"position\":\"대리\",\"fax\":\"02-1111-2222\",\"no\":101,\"name\":\"홍길동\",\"email\":\"hong@test.com\",\"registeredDate\":\"10월 5, 2021\"}}";

ManagerParam param = new Gson().fromJson(jsonStr, ManagerParam.class);

System.out.println(param.no);
System.out.println(param.title);
System.out.println(param.manager);

//맵으로 저장은 똑바로 했지만 맵으로 꺼낼땐 원하는 객체로 꺼내지지 않음.. 그래서 ,,,
//Managaram.class에 담아라라고 똑바로 시키기

3


Jackson

객체 --> JSON 문자열 : 객체의 필드 값을 json 형식의 문자열로 만들기

    // 1) 객체 준비
    Member m = new Member();
    m.setNo(100);
    m.setName("홍길동");
    m.setEmail("hong@test.com");
    m.setPassword("1111");
    m.setPhoto("hong.gif");
    m.setTel("010-2222-1111");
    m.setRegisteredDate(new Date(System.currentTimeMillis()));

    // 2) JSON 처리 객체 준비
    ObjectMapper mapper = new ObjectMapper();

    // 3) 객체의 값을 JSON 문자열로 얻기
    String jsonStr = mapper.writeValueAsString(m);

    System.out.println(jsonStr);

JSON 문자열 --> 객체 : JSON 문자열을 해석하여 객체를 생성하기

    // 1) JSON 문자열 준비
    String jsonStr = "{\"no\":100,\"name\":\"홍길동\",\"email\":\"hong@test.com\",
    \"password\":\"1111\",\"photo\":\"hong.gif\",\"tel\":\"010-2222-1111\",\"registeredDate\":1642991105179}";

    // 2) JSON 처리 객체 준비
    ObjectMapper mapper = new ObjectMapper();

    // 3) JSON 문자열을 가지고 객체 만들기
    Member m = mapper.readValue(jsonStr, Member.class);

    System.out.println(m);

**

주의!

Gson 과 달리 JSON 프로퍼티에 해당하는 객체 프로퍼티가 없다면 예외가 발생한다.

JsonIgnoreProperties 처리를 해줘야함.

객체 --> JSON 문자열 : Date 값을 yyyy-MM-dd 형식으로 출력하기

 // 1) 객체 준비
    Member m1 = new Member();
    m1.setRegisteredDate(new Date(System.currentTimeMillis()));

    ObjectMapper mapper = new ObjectMapper();
    mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));

    String jsonStr = mapper.writeValueAsString(m1);

    System.out.println(jsonStr);
String jsonStr = "{\"registeredDate\":\"2023-07-03\"}";
		 
		 ObjectMapper mapper = new ObjectMapper();
		 Member member = mapper.readValue(jsonStr, Member.class);
		 
		 System.out.println(member);